源码快照 @ 2026-09-02 (source-only, 剔除非源码素材)

This commit is contained in:
agent-radar
2026-09-02 01:05:41 +08:00
commit 04bac1f6e2
2200 changed files with 489415 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
{
"name": "@openwork/connect-link",
"private": true,
"type": "module",
"exports": {
".": {
"types": "./src/index.ts",
"development": "./src/index.ts",
"default": "./dist/index.js"
},
"./node": {
"types": "./src/node.ts",
"development": "./src/node.ts",
"default": "./dist/node.js"
}
},
"files": [
"dist",
"src"
],
"scripts": {
"build": "tsup",
"typecheck": "tsc -p tsconfig.json --noEmit",
"test": "bun test"
},
"dependencies": {
"@openwork/types": "workspace:*",
"zod": "4.3.6"
},
"devDependencies": {
"@types/node": "^22.10.2",
"tsup": "^8.5.0",
"typescript": "^5.6.3"
}
}
+102
View File
@@ -0,0 +1,102 @@
import { z } from "zod"
import {
CONNECT_LINK_AUDIENCE,
CONNECT_LINK_ROUTE,
CONNECT_LINK_VERSION,
type ConnectLinkClaims,
} from "@openwork/types/connect-link"
export {
CONNECT_LINK_ALGORITHM,
CONNECT_LINK_AUDIENCE,
CONNECT_LINK_DEFAULT_TTL_HOURS,
CONNECT_LINK_EXCHANGE_TTL_MINUTES,
CONNECT_LINK_MAX_TTL_HOURS,
CONNECT_LINK_ROUTE,
CONNECT_LINK_VERSION,
} from "@openwork/types/connect-link"
export type {
ConnectLinkBrand,
ConnectLinkClaims,
ConnectLinkDenTarget,
ConnectLinkOrg,
ConnectLinkTransport,
ConnectLinkVerifyErrorCode,
ConnectLinkVerifyFailure,
ConnectLinkVerifyResult,
ConnectLinkVerifySuccess,
} from "@openwork/types/connect-link"
export const connectLinkClaimsSchema = z.object({
iss: z.string().trim().url(),
aud: z.literal(CONNECT_LINK_AUDIENCE),
iat: z.number().int().nonnegative(),
exp: z.number().int().nonnegative(),
jti: z.string().trim().min(8),
v: z.literal(CONNECT_LINK_VERSION),
org: z.object({
name: z.string().trim().min(1).max(128),
}),
brand: z.object({
appName: z.string().trim().min(1).max(64),
logoUrl: z.string().trim().url().nullable(),
iconUrl: z.string().trim().url().nullable(),
}),
den: z.object({
baseUrl: z.string().trim().url(),
apiBaseUrl: z.string().trim().url().nullish(),
}),
requireSignin: z.boolean(),
}).meta({ ref: "ConnectLinkClaims" }) satisfies z.ZodType<ConnectLinkClaims>
const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]", "::1"])
export function isLoopbackUrl(rawUrl: string): boolean {
try {
return LOOPBACK_HOSTS.has(new URL(rawUrl).hostname)
} catch {
return false
}
}
/** Returns the first claim URL refused by the transport policy. */
export function findRefusedConnectLinkUrl(
claims: ConnectLinkClaims,
allowInsecureLoopback = false,
): string | null {
const candidates = [
claims.den.baseUrl,
claims.den.apiBaseUrl ?? null,
claims.brand.logoUrl,
claims.brand.iconUrl,
]
for (const candidate of candidates) {
if (!candidate) continue
let parsed: URL
try {
parsed = new URL(candidate)
} catch {
return candidate
}
if (parsed.protocol !== "https:" && !(allowInsecureLoopback && isLoopbackUrl(candidate))) {
return candidate
}
}
return null
}
/** Returns the first non-HTTPS claim URL, including loopback URLs. */
export function findInsecureConnectLinkUrl(claims: ConnectLinkClaims): string | null {
return findRefusedConnectLinkUrl(claims)
}
export function buildConnectDeepLink(token: string, scheme = "openwork"): string {
return `${scheme}://${CONNECT_LINK_ROUTE}?token=${encodeURIComponent(token)}`
}
export function buildConnectExchangeDeepLink(code: string, apiBaseUrl: string, scheme = "openwork"): string {
const url = new URL(`${scheme}://${CONNECT_LINK_ROUTE}`)
url.searchParams.set("code", code)
url.searchParams.set("apiBaseUrl", apiBaseUrl)
return url.toString()
}
+179
View File
@@ -0,0 +1,179 @@
// Node-only signing/verification for connect-link tokens (compact JWS,
// EdDSA/Ed25519 via node:crypto — no external JWT dependency). den-api signs
// with this module; the Electron main process ships its own dependency-free
// mirror of `verifyConnectLinkToken` (apps/desktop/electron/connect-link.mjs)
// and this implementation is the reference the tests hold it to.
import { Buffer } from "node:buffer"
import { createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify } from "node:crypto"
import {
CONNECT_LINK_ALGORITHM,
CONNECT_LINK_AUDIENCE,
CONNECT_LINK_VERSION,
type ConnectLinkClaims,
type ConnectLinkVerifyResult,
} from "@openwork/types/connect-link"
import { connectLinkClaimsSchema, findInsecureConnectLinkUrl, findRefusedConnectLinkUrl } from "./index"
const DEFAULT_CLOCK_SKEW_SECONDS = 60
export type ConnectLinkKeyPair = {
publicKeyPem: string
privateKeyPem: string
}
export function generateConnectLinkKeyPair(): ConnectLinkKeyPair {
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
publicKeyEncoding: { type: "spki", format: "pem" },
privateKeyEncoding: { type: "pkcs8", format: "pem" },
})
return { publicKeyPem: publicKey, privateKeyPem: privateKey }
}
function base64UrlEncode(value: string): string {
return Buffer.from(value, "utf8").toString("base64url")
}
function base64UrlDecode(value: string): string | null {
if (!/^[A-Za-z0-9_-]+$/.test(value)) return null
try {
return Buffer.from(value, "base64url").toString("utf8")
} catch {
return null
}
}
export type SignConnectLinkTokenInput = {
claims: ConnectLinkClaims
privateKeyPem: string
kid: string
/** Permit non-https den/logo URLs (local development and evals only). */
allowInsecureUrls?: boolean
}
export function signConnectLinkToken(input: SignConnectLinkTokenInput): string {
const claims = connectLinkClaimsSchema.parse(input.claims)
if (!input.allowInsecureUrls) {
const insecure = findInsecureConnectLinkUrl(claims)
if (insecure) {
throw new Error(`connect-link claims contain a non-https URL: ${insecure}`)
}
}
const header = { alg: CONNECT_LINK_ALGORITHM, typ: "JWT", kid: input.kid }
const signingInput = `${base64UrlEncode(JSON.stringify(header))}.${base64UrlEncode(JSON.stringify(claims))}`
// new Uint8Array(...) keeps the calls assignable across the @types/node
// versions in this workspace (Buffer's backing store is typed as
// ArrayBufferLike on older lib combinations).
const signature = sign(null, new Uint8Array(Buffer.from(signingInput, "utf8")), createPrivateKey(input.privateKeyPem))
return `${signingInput}.${signature.toString("base64url")}`
}
export type VerifyConnectLinkTokenInput = {
token: string
/** kid → SPKI PEM public key. Only keys in this map are trusted. */
publicKeys: Record<string, string>
nowEpochSeconds?: number
clockSkewSeconds?: number
/** Accept http URLs when every insecure target is loopback (dev only). */
allowInsecureLoopback?: boolean
}
export function verifyConnectLinkToken(input: VerifyConnectLinkTokenInput): ConnectLinkVerifyResult {
const now = input.nowEpochSeconds ?? Math.floor(Date.now() / 1000)
const skew = input.clockSkewSeconds ?? DEFAULT_CLOCK_SKEW_SECONDS
const parts = input.token.split(".")
if (parts.length !== 3 || parts.some((part) => part.length === 0)) {
return { ok: false, code: "invalid_token", message: "Token is not a three-part compact JWS." }
}
const [headerPart, payloadPart, signaturePart] = parts
const headerJson = base64UrlDecode(headerPart)
if (headerJson === null) {
return { ok: false, code: "invalid_token", message: "Token header is not valid base64url." }
}
let header: unknown
try {
header = JSON.parse(headerJson)
} catch {
return { ok: false, code: "invalid_token", message: "Token header is not valid JSON." }
}
if (typeof header !== "object" || header === null) {
return { ok: false, code: "invalid_token", message: "Token header is not an object." }
}
const headerRecord = header as Record<string, unknown>
if (headerRecord.alg !== CONNECT_LINK_ALGORITHM) {
return { ok: false, code: "invalid_token", message: `Token alg must be ${CONNECT_LINK_ALGORITHM}.` }
}
if ("crit" in headerRecord) {
return { ok: false, code: "invalid_token", message: "Token crit header is not supported." }
}
if (headerRecord.typ !== undefined && headerRecord.typ !== "JWT") {
return { ok: false, code: "invalid_token", message: "Token typ must be JWT when present." }
}
const kid = headerRecord.kid
if (typeof kid !== "string" || kid.length === 0) {
return { ok: false, code: "invalid_token", message: "Token kid header is required." }
}
const publicKeyPem = input.publicKeys[kid]
if (!publicKeyPem) {
return { ok: false, code: "unknown_kid", message: `No trusted key for kid ${kid}.` }
}
if (!/^[A-Za-z0-9_-]+$/.test(signaturePart)) {
return { ok: false, code: "invalid_token", message: "Token signature is not valid base64url." }
}
const signingInput = new Uint8Array(Buffer.from(`${headerPart}.${payloadPart}`, "utf8"))
const signature = new Uint8Array(Buffer.from(signaturePart, "base64url"))
let signatureValid = false
try {
signatureValid = verify(null, signingInput, createPublicKey(publicKeyPem), signature)
} catch {
signatureValid = false
}
if (!signatureValid) {
return { ok: false, code: "bad_signature", message: "Token signature does not verify." }
}
const payloadJson = base64UrlDecode(payloadPart)
if (payloadJson === null) {
return { ok: false, code: "invalid_token", message: "Token payload is not valid base64url." }
}
let payload: unknown
try {
payload = JSON.parse(payloadJson)
} catch {
return { ok: false, code: "invalid_token", message: "Token payload is not valid JSON." }
}
if (typeof payload !== "object" || payload === null) {
return { ok: false, code: "invalid_token", message: "Token payload is not an object." }
}
const payloadRecord = payload as Record<string, unknown>
if (payloadRecord.aud !== CONNECT_LINK_AUDIENCE) {
return { ok: false, code: "wrong_audience", message: "Token audience is not the desktop connect audience." }
}
if (payloadRecord.v !== CONNECT_LINK_VERSION) {
return { ok: false, code: "wrong_version", message: "Token payload version is not supported." }
}
const parsed = connectLinkClaimsSchema.safeParse(payload)
if (!parsed.success) {
return { ok: false, code: "malformed_claims", message: "Token claims failed validation." }
}
const claims = parsed.data
if (claims.iat > now + skew) {
return { ok: false, code: "not_yet_valid", message: "Token is not valid yet." }
}
if (claims.exp <= now - skew) {
return { ok: false, code: "expired", message: "Token has expired." }
}
const refusedUrl = findRefusedConnectLinkUrl(claims, input.allowInsecureLoopback === true)
if (refusedUrl) {
return { ok: false, code: "insecure_url", message: `Token target is not https: ${refusedUrl}` }
}
return { ok: true, claims, transport: "signed", kid }
}
@@ -0,0 +1,122 @@
import { describe, expect, test } from "bun:test"
import { Buffer } from "node:buffer"
import { createPrivateKey, sign } from "node:crypto"
import {
buildConnectDeepLink,
buildConnectExchangeDeepLink,
CONNECT_LINK_AUDIENCE,
type ConnectLinkClaims,
} from "../src/index"
import {
generateConnectLinkKeyPair,
signConnectLinkToken,
verifyConnectLinkToken,
} from "../src/node"
const NOW = 1_783_000_000
const KID = "owc-test"
const { publicKeyPem, privateKeyPem } = generateConnectLinkKeyPair()
const publicKeys = { [KID]: publicKeyPem }
function claims(overrides: Partial<ConnectLinkClaims> = {}): ConnectLinkClaims {
return {
iss: "https://api.openwork.acme.example.com",
aud: CONNECT_LINK_AUDIENCE,
iat: NOW,
exp: NOW + 72 * 3600,
jti: "test-jti-0001",
v: 1,
org: { name: "Acme Robotics" },
brand: { appName: "Acme Work", logoUrl: null, iconUrl: null },
den: {
baseUrl: "https://openwork.acme.example.com",
apiBaseUrl: "https://api.openwork.acme.example.com",
},
requireSignin: true,
...overrides,
}
}
function mintRaw(header: object, payload: object) {
const encode = (value: object) => Buffer.from(JSON.stringify(value), "utf8").toString("base64url")
const signingInput = `${encode(header)}.${encode(payload)}`
const signature = sign(null, Buffer.from(signingInput, "utf8"), createPrivateKey(privateKeyPem))
return `${signingInput}.${signature.toString("base64url")}`
}
function verifyAt(token: string, nowEpochSeconds = NOW) {
return verifyConnectLinkToken({ token, publicKeys, nowEpochSeconds })
}
describe("signed desktop connect links", () => {
test("round-trips exact organization configuration", () => {
const expected = claims()
const token = signConnectLinkToken({ claims: expected, privateKeyPem, kid: KID })
const result = verifyAt(token)
expect(result.ok).toBe(true)
if (!result.ok) throw new Error("expected valid token")
expect(result.claims).toEqual(expected)
expect(result.kid).toBe(KID)
expect(result.transport).toBe("signed")
})
test("rejects tampered payloads", () => {
const token = signConnectLinkToken({ claims: claims(), privateKeyPem, kid: KID })
const [header, , signature] = token.split(".")
const forged = Buffer.from(JSON.stringify(claims({
den: { baseUrl: "https://evil.example.com" },
}))).toString("base64url")
const result = verifyAt(`${header}.${forged}.${signature}`)
expect(result.ok).toBe(false)
if (!result.ok) expect(result.code).toBe("bad_signature")
})
test("rejects algorithm confusion, critical headers, and unknown keys", () => {
const tokens = [
mintRaw({ alg: "none", kid: KID }, claims()),
mintRaw({ alg: "HS256", typ: "JWT", kid: KID }, claims()),
mintRaw({ alg: "EdDSA", typ: "JWT", kid: KID, crit: ["exp"] }, claims()),
mintRaw({ alg: "EdDSA", typ: "JWT", kid: "other" }, claims()),
]
for (const token of tokens) {
expect(verifyAt(token).ok).toBe(false)
}
})
test("enforces expiry and issued-at with clock skew", () => {
const token = signConnectLinkToken({ claims: claims(), privateKeyPem, kid: KID })
expect(verifyAt(token, NOW + 72 * 3600 + 30).ok).toBe(true)
const expired = verifyAt(token, NOW + 72 * 3600 + 61)
expect(expired.ok).toBe(false)
if (!expired.ok) expect(expired.code).toBe("expired")
const future = verifyAt(token, NOW - 61)
expect(future.ok).toBe(false)
if (!future.ok) expect(future.code).toBe("not_yet_valid")
})
test("refuses non-HTTPS organization servers except explicit dev loopback", () => {
const insecure = claims({ den: { baseUrl: "http://intranet.example.com" } })
expect(() => signConnectLinkToken({ claims: insecure, privateKeyPem, kid: KID })).toThrow(/non-https/)
const loopback = claims({ den: { baseUrl: "http://127.0.0.1:8790" } })
const token = signConnectLinkToken({
claims: loopback,
privateKeyPem,
kid: KID,
allowInsecureUrls: true,
})
expect(verifyAt(token).ok).toBe(false)
expect(verifyConnectLinkToken({
token,
publicKeys,
nowEpochSeconds: NOW,
allowInsecureLoopback: true,
}).ok).toBe(true)
})
test("builds only the dedicated connect route", () => {
expect(buildConnectDeepLink("abc.def.ghi")).toBe("openwork://connect?token=abc.def.ghi")
expect(buildConnectExchangeDeepLink("abcdefghijklmnopqrstuvwxyz123456", "https://den.example.com/api/den"))
.toBe("openwork://connect?code=abcdefghijklmnopqrstuvwxyz123456&apiBaseUrl=https%3A%2F%2Fden.example.com%2Fapi%2Fden")
})
})
+14
View File
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"declaration": true,
"outDir": "dist",
"types": ["node"]
},
"include": ["src"]
}
+12
View File
@@ -0,0 +1,12 @@
import { defineConfig } from "tsup"
export default defineConfig({
clean: true,
dts: true,
entry: {
index: "src/index.ts",
node: "src/node.ts",
},
format: ["esm"],
target: "es2022",
})