@synap-core/sdk 1.5.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/testing/fixtures.ts","../src/testing/auth-server.ts","../src/testing/seed.ts","../src/testing/cloud.ts","../src/testing/index.ts"],"sourcesContent":["/**\n * Demo data for the mock pod. Shapes are the `@synap-core/sdk/public` wire\n * types, so a fixture that drifts from the contract fails to compile.\n */\nimport type { PublicForm, PublicRecord, PublicShare } from \"../public/client\";\n\nexport const MOCK_FORM: PublicForm = {\n title: \"Get in touch\",\n fields: [\n { key: \"name\", label: \"Name\", type: \"text\", required: true, constraints: { maxLength: 120 } },\n { key: \"email\", label: \"Email\", type: \"email\", required: true },\n {\n key: \"topic\",\n label: \"Topic\",\n type: \"enum\",\n constraints: { enum: [\"Sales\", \"Support\", \"Partnership\"] },\n },\n { key: \"message\", label: \"Message\", type: \"richtext\", help: \"A few lines is plenty.\" },\n ],\n successMessage: \"Thanks — we received your message.\",\n honeypotField: \"hp\",\n ticket: \"mock-ticket\",\n minSubmitMs: 0,\n captcha: { required: false },\n};\n\nexport const MOCK_SHARE: PublicShare = {\n resourceType: \"entity\",\n title: \"Launch notes\",\n properties: { status: \"open\", owner: \"Ada\", featured: true },\n body: {\n format: \"markdown\",\n content: [\n \"# Launch notes\",\n \"\",\n \"This page is a **published snapshot** from a Synap pod.\",\n \"\",\n \"- Read the [Synap docs](https://synap.live)\",\n \"- Links other than http, https and mailto render as plain text: [bad](javascript:alert(1))\",\n \"\",\n \"<script>raw HTML is shown as text, never run</script>\",\n ].join(\"\\n\"),\n },\n publishedOn: \"2026-09-27\",\n};\n\n/**\n * A published HTML document (an estimate), as the pod serves an `html` body: a\n * page renders it only inside `<iframe sandbox=\"\" srcdoc>`, so the script below\n * never runs.\n */\nexport const MOCK_HTML_SHARE: PublicShare = {\n resourceType: \"entity\",\n title: \"Estimate for Northwind\",\n properties: { total: \"4 800 €\", validUntil: \"2026-11-30\" },\n body: {\n format: \"html\",\n content: [\n \"<!doctype html>\",\n '<html lang=\"en\"><head><meta charset=\"utf-8\"><title>Estimate</title>',\n \"<style>body{font-family:Georgia,serif;max-width:40rem;margin:2rem auto;line-height:1.5}td{padding:.25rem .75rem}</style>\",\n \"</head><body>\",\n \"<h1>Estimate for Northwind</h1>\",\n \"<table><tr><td>Discovery workshop</td><td>1 200 €</td></tr><tr><td>Build</td><td>3 600 €</td></tr></table>\",\n \"<p><strong>Total: 4 800 €</strong></p>\",\n \"<script>document.body.textContent = 'scripts never run in a sandboxed frame'</script>\",\n \"</body></html>\",\n ].join(\"\"),\n },\n publishedOn: \"2026-10-22\",\n};\n\n/** One collection of a mock site: its door config and its live records. */\nexport interface MockCollection {\n /** Default sort keys (`-` = descending); also the sort keys the door accepts. */\n sort: string[];\n pageSize: number;\n addressing: \"slug\" | \"publicId\";\n records: PublicRecord[];\n}\n\n/** A mock published site. The manifest is derived from it (counts included). */\nexport interface MockSite {\n title?: string;\n description?: string;\n publishedOn: string;\n collections: Record<string, MockCollection>;\n}\n\n/** A public id of the door's shape (`p_` + 16 base62), deterministic. */\nfunction publicId(prefix: string, n: number): string {\n return `p_${prefix}${String(n).padStart(16 - prefix.length, \"0\")}`;\n}\n\nfunction slugify(s: string): string {\n return s\n .normalize(\"NFKD\")\n .replace(/[̀-ͯ]/g, \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 96);\n}\n\nconst PAPER_TITLES = [\n \"Sparse graphs at scale\",\n \"Learning to rank, revisited\",\n \"A note on causal tracing\",\n \"Small models, long contexts\",\n \"Evaluating retrieval honestly\",\n \"Robust tokenisation\",\n \"Graphs that forget\",\n \"Calibration under shift\",\n \"Latent space cartography\",\n \"Proofs as programs, again\",\n \"Cheap uncertainty\",\n \"Résumé of a decade\",\n];\nconst VENUES = [\"NeurIPS\", \"ICML\", \"ACL\", \"ICLR\"];\n\nconst PAPERS: PublicRecord[] = PAPER_TITLES.map((title, i) => ({\n collection: \"paper\",\n publicId: publicId(\"paper\", i + 1),\n slug: slugify(title),\n title,\n properties: {\n year: 2026 - (i % 5),\n venue: VENUES[i % VENUES.length],\n open: i % 3 !== 0,\n },\n publishedOn: `2026-09-${String(28 - i).padStart(2, \"0\")}`,\n body: i % 4 === 3 ? null : { format: \"markdown\", content: `# ${title}\\n\\nAbstract of **${title}**.` },\n}));\n\nconst PEOPLE: PublicRecord[] = [\"Ada Lovelace\", \"Alan Turing\", \"Grace Hopper\"].map((name, i) => ({\n collection: \"person\",\n publicId: publicId(\"person\", i + 1),\n slug: null,\n title: name,\n properties: { name, role: i === 0 ? \"Lead\" : \"Researcher\" },\n publishedOn: \"2026-09-01\",\n body: null,\n}));\n\n/**\n * The demo site: `paper` (12 records, 5 per page, by slug: pagination),\n * `person` (by public id), `event` (nothing published: the empty state).\n */\nexport const MOCK_SITE: MockSite = {\n title: \"Demo lab\",\n description: \"What the lab publishes\",\n publishedOn: \"2026-09-01\",\n collections: {\n paper: { sort: [\"-year\"], pageSize: 5, addressing: \"slug\", records: PAPERS },\n person: { sort: [\"name\"], pageSize: 20, addressing: \"publicId\", records: PEOPLE },\n event: { sort: [], pageSize: 10, addressing: \"slug\", records: [] },\n },\n};\n","/**\n * A mock pod for pod-app sign-in: its OAuth authorization server (RFC 8414\n * metadata, /authorize as a function standing in for the consent screen,\n * /token, /revoke) and a few Hub REST doors behind the Bearer token. Inject\n * `fetch` into the REAL `@synap-core/sdk/connect` (`createPodAppAuth({ fetch })`)\n * so everything above the wire is the production path. No network.\n *\n * Wire behaviour mirrors synap-backend `routers/oauth/routes.ts` for a CIMD\n * client: `iss` on every authorization answer (RFC 9207), PKCE S256 checked at\n * /token, single-use codes bound to client_id + redirect_uri + resource, the\n * token response's `synap_grant` / `synap_user`. Refresh mirrors the pod's\n * (`routers/oauth/refresh.ts`): rotating and single-use, 30 days from issue;\n * a token presented AGAIN after its use is a reuse that revokes its whole\n * family AND the live access key; a new code ends the client's older\n * families; /revoke with a refresh token kills its family and access key.\n * The reuse grace: within 30 s of its use, a spent token presented\n * again with its own client_id gets the SAME pair its first use got (the\n * successor refresh token and the live key, `expires_in` = what that key has\n * left), as long as the successor is unused; past it, a reuse.\n * `refresh: false` is a pod without refresh tokens (no refresh_token at all).\n *\n * Hub REST: `GET /users/me`, `GET /entities` (an ARRAY of entities, as the pod\n * answers; the seeds plus what applied writes created), `GET /proposals`\n * (`{ proposals, limit, offset, total, hasMore }`, rows only in spaces where\n * the token holds `proposal.read`, as the pod's grant clause; `proposalIds`),\n * governed writes. 1.5, from `seed` (one JSON shape, ./seed.ts):\n * `GET /entities/:id` (404 with an empty body, as the pod), `GET\n * /entities/:id/connections` (`{ connections, counts }`: seeded relations and\n * the sessions about it), `GET /documents/:id` (`{ document }`), `GET\n * /focus-sessions` (an ARRAY; `workspaceId` or `projectId` required; status,\n * limit 1-50, lens, kind, subjectEntityId), `POST /proposals/:id/approve`.\n *\n * Who the token acts as: `actsAs: \"person\"` answers\n * `synap_acts_as: \"person\"`, applies writes directly (unless `writeMode`\n * says otherwise) and lets the token approve where it holds\n * `proposal.approve`; `\"agent\"` answers `\"agent\"`; omitted, the field is not\n * sent (a pod that does not name it) and the token is an agent's. An agent's approve is\n * refused 403, as the pod's `rejectAgentReviewer`.\n *\n * mock.authorize(authorizeUrl) → the callback URL (approved)\n * mock.authorize(authorizeUrl, { deny: true }) → error=access_denied\n * mock.authorize(authorizeUrl, { iss: \"https://evil.example\" }) → a mix-up attempt\n * mock.loseNextRefreshRace() → the next redeem is a concurrent loser that found no successor (refused, no revoke)\n * mock.redeemElsewhere(t) → another app instance rotated t (presenting it within 30 s gets that pair)\n * mock.consumeRefreshToken(t) → the token was used elsewhere with no successor (presenting it is a reuse)\n * mock.revokeAll() → the person removed the app in their pod\n * mock.revokeAccessKeys() → a narrow or a pod-side \"Revoke key\": the live keys stop, the connection (its refresh token) lives\n */\nimport { pkceChallenge, randomToken } from \"../connect/encoding\";\nimport type { PodActsAs, PodGrant, PodUser } from \"../connect/types\";\nimport type { MockPodSeed, MockSeedDocument, MockSeedRelation, MockSeedSession } from \"./seed\";\n\n/** A placeholder pod origin; never contacted. */\nexport const MOCK_AUTH_ISSUER = \"https://pod.mock-synap.test\";\n\nexport const MOCK_GRANT: PodGrant[] = [\n { permission: \"entity.post.read\", workspaceId: \"ws_mock_studio\", workspaceName: \"Studio\" },\n { permission: \"entity.post.create\", workspaceId: \"ws_mock_studio\", workspaceName: \"Studio\" },\n];\n\nexport const MOCK_USER: PodUser = { id: \"user_mock_ada\", name: \"Ada Lovelace\" };\n\nexport type MockHubFailure = \"rate_limited\" | \"forbidden\" | \"door_unsupported\" | \"unreachable\" | \"server\" | \"unavailable\";\n\nexport interface MockAuthServerOptions {\n issuer?: string;\n /** Issue rotating refresh tokens. Default true; false = a pod without refresh tokens. */\n refresh?: boolean;\n /** Default 3600 (the pod's 1 h). */\n accessTtlSec?: number;\n /** Default 30 days. */\n refreshIdleSec?: number;\n /** Send `refresh_token_expires_in` with each refresh token. Default false (the pod does not say). */\n advertiseRefreshExpiry?: boolean;\n /** The reuse grace, seconds. Default 30 (the pod's); 0 = off (a pod without the grace). */\n refreshGraceSec?: number;\n /**\n * `synap_app` on token responses: the connection's id and its page on the\n * pod console. Default `MOCK_APP`; null = a pod that does not send it.\n */\n app?: { id: string; manageUrl: string | null } | null;\n /** Entities `GET /entities` answers (with `workspaceId` / `profileSlug` filters). */\n entities?: Array<Record<string, unknown>>;\n grant?: PodGrant[];\n user?: PodUser;\n /** Override or remove (undefined) metadata fields: a pod too old, a lying issuer. */\n metadata?: Record<string, unknown>;\n /**\n * Hub writes: \"proposed\" (ask-first, the default for an agent token) or\n * \"applied\" (the default for `actsAs: \"person\"`).\n */\n writeMode?: \"proposed\" | \"applied\";\n /**\n * `synap_acts_as` on token responses. Omitted = not sent (a pod that does\n * not name it; the SDK reads an agent connection).\n */\n actsAs?: PodActsAs;\n /**\n * The pod's data as one JSON shape (`parseMockPodSeed`). `seed.entities` come\n * before `entities`; `seed.spaces` put a `templateSlug` on the grant rows of\n * those spaces.\n */\n seed?: MockPodSeed;\n /** Hub paths (after /api/hub) that answer one failure. */\n failures?: Record<string, MockHubFailure>;\n now?: () => number;\n}\n\nexport interface MockAuthRequest {\n method: string;\n url: string;\n /** Lower-cased header names. */\n headers: Record<string, string>;\n /** The form body of a /token or /revoke call. */\n form: Record<string, string> | null;\n}\n\nexport interface AuthorizeDecision {\n /** The person said no. */\n deny?: boolean;\n /** Override `iss` on the answer (null = omit it): a mix-up attack. */\n iss?: string | null;\n /** Override `state` on the answer: a forged answer. */\n state?: string;\n}\n\n/** A proposal a governed write filed (`GET /proposals` lists the pending ones). */\nexport interface MockProposal {\n id: string;\n proposalType: string;\n targetType: string;\n targetId: string | null;\n status: \"pending\" | \"approved\" | \"rejected\";\n workspaceId: string | null;\n createdAt: string;\n correlationId: string | null;\n sessionId: string | null;\n agentUserId: string | null;\n summary?: string;\n}\n\n/** The connection's `synap_app` the mock pod answers by default (backend `appTokenResponse`). */\nexport const MOCK_APP = { id: \"app_mock_studio\", manageUrl: \"https://pod-admin.mock-synap.test/apps/app_mock_studio\" };\n\n/** The app's agent on the mock pod: who files its proposals. */\nexport const MOCK_APP_AGENT_ID = \"agent_mock_app\";\n\nexport interface MockAuthServer {\n issuer: string;\n fetch: typeof fetch;\n requests: MockAuthRequest[];\n /** Hub writes seen, in order. */\n writes: Array<{ method: string; path: string; body: unknown }>;\n /** Proposals: the seeded ones, then those filed by proposed writes, in order. */\n proposals: MockProposal[];\n /** Proposals approved through `POST /proposals/:id/approve`, in order. */\n approvals: string[];\n /** The person approved or rejected one: it leaves the pending list. */\n settleProposal(id: string, status: \"approved\" | \"rejected\"): void;\n /** Another instance of the app rotated `token` (its own refresh): returns the pair the pod answered it. */\n redeemElsewhere(token: string): Promise<{ access_token: string; refresh_token: string; expires_in: number }>;\n /** Refresh redeems answered within the reuse grace (the same pair again). */\n graceAnswers: number;\n /** Stand-in for the consent screen: validates the request like /authorize, returns where the pod redirects. */\n authorize(authorizeUrl: string, decision?: AuthorizeDecision): string;\n /** Mark a refresh token used elsewhere: presenting it now is a REUSE (family + live key revoked). */\n consumeRefreshToken(token: string): void;\n /** The next refresh redeem loses a concurrent race: invalid_grant, nothing revoked. */\n loseNextRefreshRace(): void;\n /** Refresh-token redeems that were reuses (each revoked a family). */\n reuses: number;\n /** The person revoked the app: every token stops working. */\n revokeAll(): void;\n /**\n * The live access keys stop working, the refresh tokens do not: what a\n * narrow (the slot's key is revoked at once) or a pod-side \"Revoke key\"\n * does. The next refresh mints a new key.\n */\n revokeAccessKeys(): void;\n /** Live (unrevoked) refresh tokens. */\n liveRefreshTokens(): string[];\n reset(): void;\n}\n\ninterface CodeRow {\n clientId: string;\n redirectUri: string;\n challenge: string;\n resource: string | null;\n scope: string[];\n}\n\ninterface AccessRow {\n expiresAt: number;\n revoked: boolean;\n family: string | null;\n scope: string[];\n}\n\ninterface RefreshRow {\n clientId: string;\n family: string;\n idleUntil: number;\n used: boolean;\n revoked: boolean;\n scope: string[];\n /** When it was spent, and the pair that use was answered (the grace re-answers it). */\n usedAt?: number;\n successor?: string;\n pairAccess?: string;\n}\n\nfunction json(status: number, body: unknown, headers: Record<string, string> = {}): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\", ...headers },\n });\n}\n\nfunction oauthError(error: string, description: string, status = 400): Response {\n return json(status, { error, error_description: description });\n}\n\nexport function createMockAuthServer(options: MockAuthServerOptions = {}): MockAuthServer {\n const issuer = options.issuer ?? MOCK_AUTH_ISSUER;\n const now = options.now ?? Date.now;\n const refresh = options.refresh ?? true;\n const accessTtl = options.accessTtlSec ?? 3600;\n const refreshIdle = options.refreshIdleSec ?? 30 * 24 * 3600;\n const grant = options.grant ?? MOCK_GRANT;\n const user = options.user ?? MOCK_USER;\n const codes = new Map<string, CodeRow>();\n const access = new Map<string, AccessRow>();\n const refreshTokens = new Map<string, RefreshRow>();\n const requests: MockAuthRequest[] = [];\n const writes: Array<{ method: string; path: string; body: unknown }> = [];\n const proposals: MockProposal[] = [];\n const seed = options.seed ?? {};\n const entities: Array<Record<string, unknown>> = [...(seed.entities ?? []), ...(options.entities ?? [])];\n const sessions: MockSeedSession[] = [...(seed.sessions ?? [])];\n const documents: MockSeedDocument[] = [...(seed.documents ?? [])];\n const relations: MockSeedRelation[] = [...(seed.relations ?? [])];\n const templateOf = new Map((seed.spaces ?? []).filter((sp) => sp.templateSlug).map((sp) => [sp.id, sp.templateSlug!]));\n const approvals: string[] = [];\n const seededAt = new Date(now()).toISOString();\n for (const p of seed.proposals ?? []) {\n proposals.push({\n proposalType: \"create\",\n targetType: \"entity\",\n targetId: null,\n status: \"pending\",\n workspaceId: null,\n createdAt: seededAt,\n correlationId: null,\n sessionId: null,\n agentUserId: null,\n ...p,\n });\n }\n const writeMode = options.writeMode ?? (options.actsAs === \"person\" ? \"applied\" : \"proposed\");\n const graceMs = (options.refreshGraceSec ?? 30) * 1000;\n const app = options.app === undefined ? MOCK_APP : options.app;\n let proposalSeq = 0;\n let graceAnswers = 0;\n\n const metadata = (): Record<string, unknown> => {\n const base: Record<string, unknown> = {\n issuer,\n authorization_endpoint: `${issuer}/authorize`,\n token_endpoint: `${issuer}/token`,\n registration_endpoint: `${issuer}/register`,\n revocation_endpoint: `${issuer}/revoke`,\n revocation_endpoint_auth_methods_supported: [\"none\"],\n response_types_supported: [\"code\"],\n grant_types_supported: refresh ? [\"authorization_code\", \"refresh_token\"] : [\"authorization_code\"],\n code_challenge_methods_supported: [\"S256\"],\n token_endpoint_auth_methods_supported: [\"none\"],\n authorization_response_iss_parameter_supported: true,\n client_id_metadata_document_supported: true,\n };\n for (const [k, v] of Object.entries(options.metadata ?? {})) {\n if (v === undefined) delete base[k];\n else base[k] = v;\n }\n return base;\n };\n\n let loseNextRace = false;\n let reuses = 0;\n const revokeFamily = (family: string) => {\n for (const r of refreshTokens.values()) if (r.family === family) r.revoked = true;\n for (const a of access.values()) if (a.family === family) a.revoked = true;\n };\n\n /** The token response; `pair` re-answers an existing access key + refresh token (the grace). */\n const tokenBody = (scope: string[], clientId: string, family: string, pair?: { accessToken: string; refreshToken: string }) => {\n const accessToken = pair?.accessToken ?? `synap_hub_mock_${randomToken()}`;\n if (!pair) access.set(accessToken, { expiresAt: now() + accessTtl * 1000, revoked: false, family: refresh ? family : null, scope });\n const row = access.get(accessToken)!;\n const body: Record<string, unknown> = {\n access_token: accessToken,\n token_type: \"Bearer\",\n // As the pod: what the key has left, never an assumed hour.\n expires_in: Math.max(0, Math.floor((row.expiresAt - now()) / 1000)),\n scope: scope.join(\" \"),\n // Each grant row names its space's template when it came from one.\n synap_grant: grant\n .filter((g) => scope.includes(g.permission))\n .map((g) => (g.templateSlug || !templateOf.has(g.workspaceId) ? g : { ...g, templateSlug: templateOf.get(g.workspaceId)! })),\n synap_user: user,\n ...(app ? { synap_app: app } : {}),\n ...(options.actsAs ? { synap_acts_as: options.actsAs } : {}),\n };\n if (pair) {\n body.refresh_token = pair.refreshToken;\n if (options.advertiseRefreshExpiry) body.refresh_token_expires_in = Math.floor((refreshTokens.get(pair.refreshToken)!.idleUntil - now()) / 1000);\n } else if (refresh) {\n const refreshToken = randomToken();\n refreshTokens.set(refreshToken, { clientId, family, idleUntil: now() + refreshIdle * 1000, used: false, revoked: false, scope });\n body.refresh_token = refreshToken;\n if (options.advertiseRefreshExpiry) body.refresh_token_expires_in = refreshIdle;\n }\n return body;\n };\n\n async function token(form: Record<string, string>): Promise<Response> {\n if (form.grant_type === \"authorization_code\") {\n const row = form.code ? codes.get(form.code) : undefined;\n if (form.code) codes.delete(form.code); // claim first: a failed exchange burns the code\n if (!row) return oauthError(\"invalid_grant\", \"Invalid, expired, or already-redeemed authorization code\");\n if (row.clientId !== form.client_id) return oauthError(\"invalid_grant\", \"client_id does not match the code\");\n if (row.redirectUri !== form.redirect_uri) return oauthError(\"invalid_grant\", \"redirect_uri mismatch\");\n if (!form.code_verifier || (await pkceChallenge(form.code_verifier)) !== row.challenge) {\n return oauthError(\"invalid_grant\", \"PKCE verification failed\");\n }\n if (form.resource !== undefined && row.resource && form.resource !== row.resource) {\n return oauthError(\"invalid_target\", \"resource does not match the authorization request\");\n }\n // The latest connect wins: a new code ends this client's older families.\n for (const r of refreshTokens.values()) if (r.clientId === row.clientId) revokeFamily(r.family);\n return json(200, tokenBody(row.scope, row.clientId, randomToken()));\n }\n if (form.grant_type === \"refresh_token\") {\n if (!refresh) return oauthError(\"unsupported_grant_type\", 'Only grant_type \"authorization_code\" is supported');\n if (!form.refresh_token || !form.client_id) return oauthError(\"invalid_request\", \"refresh_token and client_id are required\");\n const row = refreshTokens.get(form.refresh_token);\n if (!row || row.clientId !== form.client_id || row.revoked) {\n return oauthError(\"invalid_grant\", \"Invalid, expired, revoked or already-used refresh token\");\n }\n if (row.used) {\n // The same pair again, inside the grace, while the successor is unused and its key lives.\n const successor = row.successor ? refreshTokens.get(row.successor) : undefined;\n const key = row.pairAccess ? access.get(row.pairAccess) : undefined;\n const inGrace = graceMs > 0 && row.usedAt !== undefined && now() - row.usedAt < graceMs;\n if (inGrace && successor && !successor.used && !successor.revoked && key && !key.revoked && key.expiresAt > now()) {\n graceAnswers++;\n return json(200, tokenBody(row.scope, row.clientId, row.family, { accessToken: row.pairAccess!, refreshToken: row.successor! }));\n }\n reuses++;\n revokeFamily(row.family);\n return oauthError(\"invalid_grant\", \"Invalid, expired, revoked or already-used refresh token\");\n }\n if (row.idleUntil <= now()) return oauthError(\"invalid_grant\", \"Invalid, expired, revoked or already-used refresh token\");\n if (loseNextRace) {\n loseNextRace = false;\n return oauthError(\"invalid_grant\", \"Invalid, expired, revoked or already-used refresh token\");\n }\n row.used = true;\n row.usedAt = now();\n // One live key per connection: the rotation retires the family's older keys.\n for (const a of access.values()) if (a.family === row.family) a.revoked = true;\n const body = tokenBody(row.scope, row.clientId, row.family);\n row.successor = body.refresh_token as string;\n row.pairAccess = body.access_token as string;\n return json(200, body);\n }\n return oauthError(\"unsupported_grant_type\", \"Unsupported grant_type\");\n }\n\n /** A focus-session row as the list door answers it: the table's columns (defaults filled), `triage`, `kind`. */\n const sessionRow = (s: MockSeedSession): Record<string, unknown> => ({\n workspaceId: null,\n projectId: null,\n userId: user.id,\n correlationId: null,\n title: null,\n goal: \"\",\n status: \"active\",\n templateId: null,\n expectedOutputs: [],\n channelId: null,\n progress: null,\n currentStage: null,\n agentIds: [],\n closedAt: null,\n verificationReport: null,\n metadata: {},\n startedAt: seededAt,\n createdAt: seededAt,\n updatedAt: seededAt,\n kind: \"work\",\n triage: { pending: false, acceptedAt: null, acceptedBy: null },\n ...s,\n });\n\n /** The seeded read doors (1.5); null when `path` is none of them. */\n function readSeeded(path: string, query: URLSearchParams): Response | null {\n const conn = /^\\/entities\\/([^/]+)\\/connections$/.exec(path);\n if (conn) {\n const id = decodeURIComponent(conn[1]);\n const ws = query.get(\"workspaceId\");\n const limit = Math.min(Math.max(Number(query.get(\"limit\") ?? 50) || 50, 1), 200);\n const inLens = (e: Record<string, unknown>) => !ws || e.workspaceId === ws || e.workspaceId == null;\n const connections: Array<Record<string, unknown>> = [];\n const graph = relations\n .filter((r) => r.sourceEntityId === id || r.targetEntityId === id)\n .sort((a, b) => String(b.createdAt ?? \"\").localeCompare(String(a.createdAt ?? \"\")))\n .slice(0, limit);\n for (const r of graph) {\n const outgoing = r.sourceEntityId === id;\n const otherId = outgoing ? r.targetEntityId : r.sourceEntityId;\n const other = entities.find((e) => e.id === otherId);\n // As the pod: an edge whose far end is gone or out of the lens is not a neighbour.\n if (!other || !inLens(other)) continue;\n connections.push({\n entityId: otherId,\n entity: { ...other, type: other.profileSlug ?? other.type ?? null, facetSlugs: other.facetSlugs ?? [] },\n label: r.type,\n direction: outgoing ? \"outgoing\" : \"incoming\",\n source: \"graph\",\n relationId: r.id,\n relationType: r.type,\n createdAt: r.createdAt ?? null,\n });\n }\n for (const s of sessions.filter((x) => x.subjectEntityId === id).slice(0, limit)) {\n const row = sessionRow(s);\n connections.push({\n entityId: s.id,\n entity: null,\n label: (row.title as string | null) || (row.goal as string),\n direction: \"incoming\",\n source: \"focus_session\",\n focusSessionId: s.id,\n focusSessionGoal: row.goal,\n focusSessionStatus: row.status,\n focusSessionWorkspaceId: row.workspaceId,\n createdAt: row.createdAt,\n });\n }\n const n = (source: string) => connections.filter((c) => c.source === source).length;\n return json(200, {\n connections,\n counts: { total: connections.length, graph: n(\"graph\"), structural: n(\"property\"), threads: n(\"thread\"), contextChannels: n(\"context_channel\"), focusSessions: n(\"focus_session\") },\n });\n }\n const entity = /^\\/entities\\/([^/]+)$/.exec(path);\n if (entity) {\n const found = entities.find((e) => e.id === decodeURIComponent(entity[1]));\n // The pod answers a miss with an EMPTY 404 body (rest/entities.ts `c.body(null, 404)`).\n return found ? json(200, found) : new Response(null, { status: 404 });\n }\n const doc = /^\\/documents\\/([^/]+)$/.exec(path);\n if (doc) {\n const format = query.get(\"format\") ?? \"raw\";\n if (format !== \"raw\" && format !== \"readable\") return json(400, { error: \"format must be raw or readable\" });\n const d = documents.find((x) => x.id === decodeURIComponent(doc[1]));\n if (!d) return json(404, { error: \"Document not found\" });\n // projectAgentDocument; the mock has no embeds, so `readable` = `raw`, and no sections are parsed.\n return json(200, {\n document: {\n id: d.id,\n title: d.title,\n type: d.type ?? \"markdown\",\n language: d.language ?? null,\n workspaceId: d.workspaceId ?? null,\n format,\n content: d.content,\n revision: d.revision ?? 1,\n version: d.version ?? 1,\n sections: [],\n diagnostics: [],\n updatedAt: d.updatedAt ?? seededAt,\n createdAt: d.createdAt ?? seededAt,\n },\n });\n }\n if (path === \"/focus-sessions\") {\n const ws = query.get(\"workspaceId\");\n const project = query.get(\"projectId\");\n if (!ws && !project) return json(400, { error: \"workspaceId or projectId is required\" });\n const status = query.get(\"status\") ?? \"all\";\n const lens = query.get(\"lens\") ?? \"all\";\n const kind = query.get(\"kind\") ?? \"all\";\n const subject = query.get(\"subjectEntityId\");\n const limit = Math.min(Math.max(Number(query.get(\"limit\") ?? 20) || 20, 1), 50);\n const rows = sessions\n .map(sessionRow)\n .filter((r) => (!ws || r.workspaceId === ws) && (!project || r.projectId === project))\n .filter((r) => status === \"all\" || r.status === status)\n .filter((r) => {\n const pending = (r.triage as { pending?: boolean } | undefined)?.pending === true;\n return lens === \"triage\" ? pending : lens === \"default\" ? !pending : true;\n })\n .filter((r) => kind === \"all\" || r.kind === kind)\n .filter((r) => !subject || r.subjectEntityId === subject)\n .sort((a, b) => String(b.startedAt).localeCompare(String(a.startedAt)));\n return json(200, rows.slice(0, limit));\n }\n return null;\n }\n\n function hub(method: string, path: string, query: URLSearchParams, headers: Record<string, string>, body: unknown): Response | \"reject\" {\n const failure = options.failures?.[path];\n if (failure === \"unreachable\") return \"reject\";\n const bearer = /^Bearer (.+)$/.exec(headers.authorization ?? \"\")?.[1];\n const row = bearer ? access.get(bearer) : undefined;\n if (!row || row.revoked || row.expiresAt <= now()) return json(401, { error: \"Unauthorized\" });\n switch (failure) {\n case \"rate_limited\":\n return json(429, { error: \"Too many requests\" }, { \"Retry-After\": \"30\" });\n case \"forbidden\":\n return json(403, { error: \"Forbidden\" });\n case \"door_unsupported\":\n return json(403, { error: \"This door is not available to a space-scoped key\", code: \"GRANT_DOOR_UNSUPPORTED\" });\n case \"server\":\n return json(500, { error: \"Internal error\" });\n case \"unavailable\":\n return json(503, { error: \"Unavailable\" });\n }\n // The grant fence: aggregate reads are refused to a space-scoped token.\n if (path.startsWith(\"/knowledge/\") || path === \"/entities/retrieve\" || path === \"/memory/search\") {\n return json(403, { error: \"This door is not available to a space-scoped key\", code: \"GRANT_DOOR_UNSUPPORTED\" });\n }\n if (method === \"GET\" && path === \"/users/me\") return json(200, user);\n if (method === \"GET\" && path === \"/entities\") {\n // The pod answers an ARRAY (rest/entities.ts), not a page object.\n const ws = query.get(\"workspaceId\");\n const kind = query.get(\"profileSlug\");\n const offset = Number(query.get(\"offset\") ?? 0) || 0;\n const limit = Number(query.get(\"limit\") ?? 50) || 50;\n const rows = entities.filter((e) => (!ws || e.workspaceId === ws) && (!kind || e.profileSlug === kind));\n return json(200, rows.slice(offset, offset + limit));\n }\n if (method === \"GET\" && path === \"/proposals\") {\n // The grant clause: proposals are read only where the token holds proposal.read (else none, not a 403).\n const readable = new Set(grant.filter((g) => g.permission === \"proposal.read\" && row.scope.includes(g.permission)).map((g) => g.workspaceId));\n const status = query.get(\"status\") ?? \"pending\";\n const ws = query.get(\"workspaceId\");\n const limit = Math.min(Math.max(Number(query.get(\"limit\") ?? 50) || 50, 1), 200);\n const offset = Number(query.get(\"offset\") ?? 0) || 0;\n // proposalIds: comma-separated and/or repeated; present but empty matches nothing.\n const idsRaw = query.getAll(\"proposalIds\");\n const ids = idsRaw.length > 0 ? new Set(idsRaw.flatMap((v) => v.split(\",\").map((x) => x.trim()).filter(Boolean))) : null;\n const rows = proposals\n .filter((p) => p.workspaceId !== null && readable.has(p.workspaceId))\n .filter((p) => (status === \"all\" || p.status === status) && (!ws || p.workspaceId === ws))\n .filter((p) => !ids || ids.has(p.id))\n .reverse(); // newest first\n const page = rows.slice(offset, offset + limit);\n return json(200, { proposals: page, limit, offset, total: rows.length, hasMore: offset + page.length < rows.length });\n }\n if (method === \"GET\") {\n const read = readSeeded(path, query);\n if (read) return read;\n }\n const approve = method === \"POST\" ? /^\\/proposals\\/([^/]+)\\/approve$/.exec(path) : null;\n if (approve) {\n // rejectAgentReviewer: an agent credential never approves, before anything is read.\n if (options.actsAs !== \"person\") {\n return json(403, { error: \"An agent credential cannot approve proposals — approve is human review. Approve from a human session.\" });\n }\n const p = proposals.find((x) => x.id === decodeURIComponent(approve[1]));\n if (!p) return json(404, { error: \"Proposal not found\" });\n // Only where the person granted proposal.approve, for the proposal's own space.\n if (!grant.some((g) => g.permission === \"proposal.approve\" && row.scope.includes(g.permission) && g.workspaceId === p.workspaceId)) {\n return json(403, { error: \"You may not approve changes here\" });\n }\n if (p.status !== \"pending\") return json(409, { error: `The proposal is ${p.status}, not pending` });\n p.status = \"approved\";\n approvals.push(p.id);\n return json(200, { success: true, proposalId: p.id, proposal: { ...p } });\n }\n if (method !== \"GET\") {\n writes.push({ method, path, body });\n const fields = body && typeof body === \"object\" ? (body as Record<string, unknown>) : {};\n const workspaceId = typeof fields.workspaceId === \"string\" ? fields.workspaceId : null;\n if (writeMode === \"proposed\") {\n const proposalId = `prop_mock_${++proposalSeq}`;\n proposals.push({\n id: proposalId,\n proposalType: method === \"POST\" ? \"create\" : method === \"DELETE\" ? \"delete\" : \"update\",\n targetType: path.split(\"/\")[1]?.replace(/s$/, \"\") ?? \"entity\",\n targetId: null,\n status: \"pending\",\n workspaceId,\n createdAt: new Date(now()).toISOString(),\n correlationId: null,\n sessionId: null,\n agentUserId: MOCK_APP_AGENT_ID,\n ...(typeof fields.title === \"string\" ? { summary: `Create \"${fields.title}\"` } : {}),\n });\n return json(200, {\n status: \"proposed\",\n message: \"Sent for review\",\n proposalId,\n reviewUrl: `${issuer}/open/${proposalId}`,\n });\n }\n const id = `ent_mock_${writes.length}`;\n if (method === \"POST\" && path === \"/entities\") entities.push({ id, ...fields });\n return json(200, { status: \"created\", id });\n }\n return json(404, { error: \"Not found\" });\n }\n\n const mockFetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const request = typeof input === \"object\" && \"method\" in input ? input : null;\n const url = new URL(typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url);\n const method = (init?.method ?? request?.method ?? \"GET\").toUpperCase();\n const headers: Record<string, string> = {};\n new Headers(init?.headers ?? request?.headers).forEach((value, name) => {\n headers[name.toLowerCase()] = value;\n });\n const rawBody = typeof init?.body === \"string\" ? init.body : request ? await request.clone().text() : \"\";\n const isForm = (headers[\"content-type\"] ?? \"\").includes(\"application/x-www-form-urlencoded\");\n const form = isForm ? Object.fromEntries(new URLSearchParams(rawBody)) : null;\n requests.push({ method, url: url.href, headers, form });\n\n if (url.origin !== new URL(issuer).origin) throw new TypeError(`Failed to fetch: ${url.origin} is not the mock pod`);\n const path = url.pathname;\n if (method === \"GET\" && path === \"/.well-known/oauth-authorization-server\") return json(200, metadata());\n if (method === \"POST\" && path === \"/token\") return token(form ?? {});\n if (method === \"POST\" && path === \"/revoke\") {\n const t = form?.token ?? \"\";\n const r = refreshTokens.get(t);\n if (r && form?.client_id && form.client_id !== r.clientId) {\n return oauthError(\"unauthorized_client\", \"The token was not issued to this client\");\n }\n if (r) revokeFamily(r.family);\n const a = access.get(t);\n if (a) a.revoked = true;\n return new Response(null, { status: 200 });\n }\n const hubPath = /^\\/api\\/hub(\\/.*)$/.exec(path)?.[1];\n if (hubPath) {\n let body: unknown = undefined;\n try {\n body = rawBody ? JSON.parse(rawBody) : undefined;\n } catch {\n body = rawBody;\n }\n const res = hub(method, hubPath, url.searchParams, headers, body);\n if (res === \"reject\") throw new TypeError(\"Failed to fetch: mock pod unreachable\");\n return res;\n }\n return json(404, { error: \"Not found\" });\n };\n\n return {\n issuer,\n fetch: mockFetch as typeof fetch,\n requests,\n writes,\n proposals,\n approvals,\n settleProposal(id, status) {\n const p = proposals.find((x) => x.id === id);\n if (p) p.status = status;\n },\n async redeemElsewhere(t) {\n const row = refreshTokens.get(t);\n const res = await token({ grant_type: \"refresh_token\", refresh_token: t, client_id: row?.clientId ?? \"\" });\n if (res.status !== 200) throw new Error(`redeemElsewhere: the pod answered ${res.status}`);\n return (await res.json()) as { access_token: string; refresh_token: string; expires_in: number };\n },\n get graceAnswers() {\n return graceAnswers;\n },\n authorize(authorizeUrl, decision = {}) {\n const url = new URL(authorizeUrl);\n if (`${url.origin}${url.pathname}` !== `${issuer}/authorize`) throw new Error(`Not this pod's /authorize: ${authorizeUrl}`);\n const q = url.searchParams;\n const redirectUri = q.get(\"redirect_uri\");\n const clientId = q.get(\"client_id\");\n // Phase 1 (shown, never redirected): no verified redirect yet.\n if (!clientId || !redirectUri) throw new Error(\"Authorization request rejected: client_id and redirect_uri are required\");\n const answer = new URL(redirectUri);\n const state = decision.state ?? q.get(\"state\");\n const finish = (fields: Record<string, string>) => {\n for (const [k, v] of Object.entries(fields)) answer.searchParams.set(k, v);\n if (state !== null) answer.searchParams.set(\"state\", state);\n const iss = decision.iss === undefined ? issuer : decision.iss;\n if (iss !== null) answer.searchParams.set(\"iss\", iss);\n return answer.href;\n };\n if (q.get(\"response_type\") !== \"code\") return finish({ error: \"unsupported_response_type\" });\n if (q.get(\"code_challenge_method\") !== \"S256\" || !q.get(\"code_challenge\")) {\n return finish({ error: \"invalid_request\", error_description: \"PKCE S256 is required\" });\n }\n const resource = q.get(\"resource\");\n if (resource !== null && resource !== `${issuer}/api/hub` && resource !== `${issuer}/mcp`) {\n return finish({ error: \"invalid_target\" });\n }\n const scope = (q.get(\"scope\") ?? \"\").split(/\\s+/).filter(Boolean);\n if (scope.length === 0) return finish({ error: \"invalid_scope\" });\n if (decision.deny) return finish({ error: \"access_denied\" });\n const code = randomToken();\n codes.set(code, { clientId, redirectUri, challenge: q.get(\"code_challenge\")!, resource, scope });\n return finish({ code });\n },\n consumeRefreshToken(t) {\n const row = refreshTokens.get(t);\n if (row) row.used = true;\n },\n loseNextRefreshRace() {\n loseNextRace = true;\n },\n get reuses() {\n return reuses;\n },\n revokeAll() {\n for (const row of access.values()) row.revoked = true;\n for (const row of refreshTokens.values()) row.revoked = true;\n },\n revokeAccessKeys() {\n for (const row of access.values()) row.revoked = true;\n },\n liveRefreshTokens() {\n return [...refreshTokens].filter(([, r]) => !r.used && !r.revoked).map(([t]) => t);\n },\n reset() {\n requests.length = 0;\n writes.length = 0;\n },\n };\n}\n","/**\n * The mock pod's data as ONE JSON-serialisable shape, so an app's mock mode,\n * smoke and screenshots replay a recorded snapshot (one file) instead of\n * fixtures built in app code:\n *\n * import { readFileSync } from \"node:fs\";\n * const seed = parseMockPodSeed(readFileSync(\"mock/pod-seed.json\", \"utf8\"));\n * const pod = createMockAuthServer({ seed });\n *\n * Rows are the pod's wire shapes (see `@synap-core/sdk/connect` hub-types):\n * `entities` as `GET /entities` answers them, `sessions` as `GET\n * /focus-sessions` rows (missing columns get the pod's defaults), `documents`\n * as `GET /documents/:id` (`sections` and `diagnostics` answered empty),\n * `relations` as graph edges for `GET /entities/:id/connections`, `proposals`\n * as `GET /proposals?view=basic` rows, `spaces` name each granted space's\n * template (`synap_grant[].templateSlug` on the token response).\n */\nimport type { MockProposal } from \"./auth-server\";\n\nexport interface MockSeedEntity {\n id: string;\n profileSlug?: string;\n workspaceId?: string | null;\n title?: string | null;\n properties?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface MockSeedSession {\n id: string;\n workspaceId?: string | null;\n projectId?: string | null;\n goal?: string;\n status?: string;\n /** Slots; `owner: \"human\"` ones are what waits on the person. */\n expectedOutputs?: Array<Record<string, unknown>>;\n /** The entity it is about: listed among that entity's connections. */\n subjectEntityId?: string | null;\n /** ISO 8601; the list is newest first by it. */\n startedAt?: string;\n [key: string]: unknown;\n}\n\nexport interface MockSeedDocument {\n id: string;\n title: string;\n content: string;\n type?: string;\n language?: string | null;\n workspaceId?: string | null;\n revision?: number;\n version?: number;\n createdAt?: string;\n updatedAt?: string;\n}\n\nexport interface MockSeedRelation {\n id: string;\n sourceEntityId: string;\n targetEntityId: string;\n type: string;\n createdAt?: string;\n}\n\nexport interface MockSeedSpace {\n id: string;\n name: string;\n /** The template it came from (e.g. `content-os`); absent = made by hand. */\n templateSlug?: string;\n}\n\nexport interface MockPodSeed {\n entities?: MockSeedEntity[];\n sessions?: MockSeedSession[];\n documents?: MockSeedDocument[];\n relations?: MockSeedRelation[];\n /** Missing fields default to a pending `create` of an `entity`, with null ids and the seed's load time. */\n proposals?: Array<Partial<MockProposal> & { id: string }>;\n spaces?: MockSeedSpace[];\n}\n\nconst KEYS = [\"entities\", \"sessions\", \"documents\", \"relations\", \"proposals\", \"spaces\"] as const;\n\n/** Required string fields per collection (the rest is free-form, as the pod's rows). */\nconst REQUIRED: Record<(typeof KEYS)[number], readonly string[]> = {\n entities: [\"id\"],\n sessions: [\"id\"],\n documents: [\"id\", \"title\", \"content\"],\n relations: [\"id\", \"sourceEntityId\", \"targetEntityId\", \"type\"],\n proposals: [\"id\"],\n spaces: [\"id\", \"name\"],\n};\n\n/**\n * Read a seed (JSON text or an already-parsed value) and check its shape:\n * every collection optional, each an array of objects carrying its required\n * string fields; unknown top-level keys are refused (a typo would otherwise\n * seed nothing). Throws `TypeError` naming the first bad path.\n */\nexport function parseMockPodSeed(input: string | unknown): MockPodSeed {\n const value: unknown = typeof input === \"string\" ? JSON.parse(input) : input;\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new TypeError(\"seed: expected an object\");\n const obj = value as Record<string, unknown>;\n for (const key of Object.keys(obj)) {\n if (!(KEYS as readonly string[]).includes(key)) throw new TypeError(`seed.${key}: unknown collection (expected ${KEYS.join(\", \")})`);\n }\n for (const key of KEYS) {\n const rows = obj[key];\n if (rows === undefined) continue;\n if (!Array.isArray(rows)) throw new TypeError(`seed.${key}: expected an array`);\n rows.forEach((row, i) => {\n if (!row || typeof row !== \"object\" || Array.isArray(row)) throw new TypeError(`seed.${key}[${i}]: expected an object`);\n for (const field of REQUIRED[key]) {\n if (typeof (row as Record<string, unknown>)[field] !== \"string\") throw new TypeError(`seed.${key}[${i}].${field}: expected a string`);\n }\n });\n }\n // A JSON round trip: what the mock serves is what a file could hold.\n return JSON.parse(JSON.stringify(obj)) as MockPodSeed;\n}\n","/**\n * A mock Synap Cloud pod chooser (Control Plane `GET /connect/pod`)\n * for \"Continue with Synap Cloud\" tests and a kit's mock mode. No network:\n * `choose()` stands in for the person signing in to the CP and picking a pod.\n *\n * Wire behaviour mirrors the CP route: it accepts only\n * `client_id` (an https CIMD URL; http on loopback only with\n * `allowInsecureLoopback`, for a kit's mock mode on http://localhost) and\n * `state` (`^[A-Za-z0-9._~-]{16,256}$`),\n * takes the return URL from the app's client metadata (`initiate_login_uri`),\n * never from the query, and answers `<initiate_login_uri>?iss=<pod issuer>&state=<state>`.\n * It never sees a code or a token.\n *\n * const cloud = createMockCloud();\n * createPodAppAuth({ ...config, cloudUrl: cloud.url });\n * cloud.choose(location, { pod: mockPod.issuer, metadata: auth.metadata }) → the app's return URL\n */\nimport { CLOUD_STATE_RE as STATE_RE, LOOPBACK_HOSTS } from \"../connect/rules\";\nimport type { ClientMetadataDocument } from \"../connect/types\";\n\n/** A placeholder Control Plane origin; never contacted. */\nexport const MOCK_CLOUD_URL = \"https://cp.mock-synap.test\";\n\n\nexport interface MockCloud {\n url: string;\n /** The chooser URLs the app sent browsers to. */\n requests: string[];\n /**\n * The person picks `pod` on the chooser: validates the request like the CP,\n * returns where the CP redirects the browser. Throws on a request the CP\n * refuses (shown as a page there, never redirected).\n */\n choose(location: string, opts: { pod: string; metadata: Pick<ClientMetadataDocument, \"client_id\" | \"initiate_login_uri\"> }): string;\n /** The person cancels on the chooser: `<initiate_login_uri>?state=…&error=access_denied`, no `iss`. */\n cancel(location: string, opts: { metadata: Pick<ClientMetadataDocument, \"client_id\" | \"initiate_login_uri\"> }): string;\n}\n\nexport function createMockCloud(options: { url?: string; allowInsecureLoopback?: boolean } = {}): MockCloud {\n const base = (options.url ?? MOCK_CLOUD_URL).replace(/\\/+$/, \"\");\n const requests: string[] = [];\n return {\n url: base,\n requests,\n choose(location, { pod, metadata }) {\n const back = check(location, metadata);\n back.searchParams.set(\"iss\", pod);\n back.searchParams.set(\"state\", new URL(location).searchParams.get(\"state\")!);\n return back.href;\n },\n cancel(location, { metadata }) {\n const back = check(location, metadata);\n back.searchParams.set(\"state\", new URL(location).searchParams.get(\"state\")!);\n back.searchParams.set(\"error\", \"access_denied\");\n return back.href;\n },\n };\n\n /** Validates like the CP (an HTML error there, never a redirect); returns the app's initiate_login_uri. */\n function check(location: string, metadata: Pick<ClientMetadataDocument, \"client_id\" | \"initiate_login_uri\">): URL {\n requests.push(location);\n const url = new URL(location);\n if (`${url.origin}${url.pathname}` !== `${base}/connect/pod`) throw new Error(`Not this CP's /connect/pod: ${location}`);\n const clientId = url.searchParams.get(\"client_id\");\n const state = url.searchParams.get(\"state\");\n if (!clientId || !cimdUrlAccepted(clientId)) throw new Error(\"Chooser refused: client_id must be an https CIMD URL\");\n if (!state || !STATE_RE.test(state)) throw new Error(\"Chooser refused: state is missing or malformed\");\n if (clientId !== metadata.client_id) throw new Error(\"Chooser refused: the client metadata is not this client_id's\");\n return new URL(metadata.initiate_login_uri);\n }\n\n /** https; http only on a loopback host, and only with `allowInsecureLoopback`. */\n function cimdUrlAccepted(clientId: string): boolean {\n let url: URL;\n try {\n url = new URL(clientId);\n } catch {\n return false;\n }\n if (url.protocol === \"https:\") return true;\n return url.protocol === \"http:\" && options.allowInsecureLoopback === true && LOOPBACK_HOSTS.has(url.hostname);\n }\n}\n","/**\n * @synap-core/sdk/testing — a mock pod: a fake `fetch` that answers the pod's\n * public doors (forms, shares, sites) from fixtures, with no network. Inject\n * it into the REAL client (`createPublicClient({ podUrl, fetch: pod.fetch })`)\n * so everything above the wire — status handling, typed errors, the models —\n * is the production path. For unit tests, a site's mock mode and a kit's\n * states gallery.\n *\n * Wire behaviour mirrors the backend doors: the uniform 404 for every miss,\n * the constant 202 on a submit, the site doors' query bounds (400), weak\n * ETags with If-None-Match → 304. Like a browser against the real doors, a\n * `credentials: \"include\"` request is refused (it rejects, as a CORS failure\n * does); with `{ browser: true }` a non-safelisted request header is too.\n *\n * tokens MOCK_TOKENS.form / .share / .htmlShare / .site the demo form, shares (markdown, html) and site\n * tokens MOCK_FAILURE_TOKENS.* one failure on every door\n * anything else the uniform 404\n *\n * Pod-app sign-in (`@synap-core/sdk/connect`): `createMockAuthServer()`, see\n * ./auth-server.ts, seeded from one JSON shape (`parseMockPodSeed`, ./seed.ts); Synap Cloud's pod chooser: `createMockCloud()`, ./cloud.ts.\n */\nimport type {\n PublicCollectionPage,\n PublicForm,\n PublicRecord,\n PublicRecordSummary,\n PublicShare,\n PublicSite,\n} from \"../public/client\";\nimport { MOCK_FORM, MOCK_HTML_SHARE, MOCK_SHARE, MOCK_SITE, type MockSite } from \"./fixtures\";\n\nexport { MOCK_FORM, MOCK_HTML_SHARE, MOCK_SHARE, MOCK_SITE };\nexport type { MockCollection, MockSite } from \"./fixtures\";\n// Pod-app sign-in: a mock authorization server + Hub REST doors.\nexport * from \"./auth-server\";\n// The mock pod's data as one JSON shape (1.5).\nexport * from \"./seed\";\n// Synap Cloud: a mock Control Plane pod chooser.\nexport * from \"./cloud\";\n\n/** A placeholder origin; never contacted. */\nexport const MOCK_POD_URL = \"https://mock.synap.invalid\";\n\nexport const MOCK_TOKENS = { form: \"demo-form\", share: \"demo\", htmlShare: \"demo-html\", site: \"demo-site\" } as const;\n\n/** The `Retry-After` the `rateLimitedRetryAfter` token sends. */\nexport const MOCK_RETRY_AFTER_SEC = 30;\n\n/** Tokens that make every door answer one failure, so each UI state can be rendered. */\nexport const MOCK_FAILURE_TOKENS = {\n /** 429 with no `Retry-After` (what the pod's public doors send today). */\n rateLimited: \"mock-rate-limited\",\n /** 429 with `Retry-After: 30`. */\n rateLimitedRetryAfter: \"mock-rate-limited-retry-after\",\n /** 403 `public_doors_disabled`: the owner switched public pages off. */\n doorsDisabled: \"mock-doors-disabled\",\n /** 500. */\n serverError: \"mock-server-error\",\n /** 503 (a read: `pod_unreachable` / `server`; a submit: `unavailable`). */\n unavailable: \"mock-unavailable\",\n /** No answer: the fetch rejects (`network` / `pod_unreachable`). */\n unreachable: \"mock-unreachable\",\n} as const;\n\nexport interface MockPodOptions {\n /** Forms by token (default: the demo form under `MOCK_TOKENS.form`). */\n forms?: Record<string, PublicForm>;\n /** Shares by token (default: the demo share under `MOCK_TOKENS.share`). */\n shares?: Record<string, PublicShare>;\n /** Sites by token (default: the demo site under `MOCK_TOKENS.site`). */\n sites?: Record<string, MockSite>;\n /** Refuse non-safelisted request headers, as a browser's CORS preflight would. */\n browser?: boolean;\n}\n\nexport interface MockRequest {\n method: string;\n url: string;\n /** Lower-cased header names. */\n headers: Record<string, string>;\n credentials: RequestCredentials | undefined;\n}\n\nexport interface MockSubmission {\n token: string;\n /** The parsed envelope (`fields`, `ticket`, `hp`, …). */\n body: unknown;\n /** The answer the mock gave. */\n status: 202 | 422;\n}\n\nexport interface MockPod {\n podUrl: string;\n fetch: typeof fetch;\n /** Every request seen, in order (assert credentials and headers on it). */\n requests: MockRequest[];\n /** Every submit seen, in order. */\n submissions: MockSubmission[];\n /** Forget `requests` and `submissions`. */\n reset(): void;\n}\n\nconst NOT_FOUND = { error: \"Not found\" };\nconst DOORS_DISABLED = {\n error: \"The owner has not turned on public pages and forms for this workspace.\",\n code: \"public_doors_disabled\",\n};\n/** Request headers a browser sends cross-origin without a preflight. */\nconst SAFELISTED = new Set([\"accept\", \"accept-language\", \"content-language\", \"content-type\"]);\n/** The only request header the real doors allow on a preflight. */\nconst PREFLIGHT_ALLOWED = new Set([\"content-type\"]);\n\nconst PUBLIC_ID_RE = /^p_[A-Za-z0-9]{16}$/;\nconst SLUG_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;\nconst SLUG_MAX_LENGTH = 96;\nconst DIGITS = /^\\d{1,9}$/;\nconst SORT_TERM = /^(-?)([A-Za-z][A-Za-z0-9_]{0,63})$/;\nconst MAX_OFFSET = 10_000;\nconst MAX_LIMIT = 100;\nconst MAX_SORT_KEYS = 3;\nconst PUBLISHED_AT = \"publishedAt\";\n\nfunction json(status: number, body: unknown, headers: Record<string, string> = {}): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-cache\", ...headers },\n });\n}\n\n/** FNV-1a, 32 bits: a stable weak validator, no crypto needed. */\nfunction weakEtag(value: unknown): string {\n let h = 0x811c9dc5;\n for (const ch of JSON.stringify(value)) {\n h ^= ch.charCodeAt(0);\n h = Math.imul(h, 0x01000193) >>> 0;\n }\n return `W/\"${h.toString(16).padStart(8, \"0\")}\"`;\n}\n\nfunction etagMatches(header: string | null, etag: string): boolean {\n if (!header) return false;\n if (header.trim() === \"*\") return true;\n const strip = (t: string) => t.trim().replace(/^W\\//, \"\");\n return header.split(\",\").some((t) => strip(t) === strip(etag));\n}\n\nfunction failure(token: string): Response | \"reject\" | null {\n switch (token) {\n case MOCK_FAILURE_TOKENS.rateLimited:\n return json(429, { error: \"Too many requests\", retryAfter: \"5 minutes\" });\n case MOCK_FAILURE_TOKENS.rateLimitedRetryAfter:\n return json(429, { error: \"Too many requests\" }, { \"Retry-After\": String(MOCK_RETRY_AFTER_SEC) });\n case MOCK_FAILURE_TOKENS.doorsDisabled:\n return json(403, DOORS_DISABLED);\n case MOCK_FAILURE_TOKENS.serverError:\n return json(500, { error: \"Internal error\" });\n case MOCK_FAILURE_TOKENS.unavailable:\n return json(503, { received: false });\n case MOCK_FAILURE_TOKENS.unreachable:\n return \"reject\";\n default:\n return null;\n }\n}\n\nfunction summary(record: PublicRecord): PublicRecordSummary {\n const { body: _body, ...rest } = record;\n return rest;\n}\n\nfunction manifest(site: MockSite): PublicSite {\n return {\n ...(site.title !== undefined ? { title: site.title } : {}),\n ...(site.description !== undefined ? { description: site.description } : {}),\n publishedOn: site.publishedOn,\n collections: Object.keys(site.collections)\n .sort()\n .map((key) => {\n const c = site.collections[key];\n return { key, count: c.records.length, sort: [...c.sort], pageSize: c.pageSize, addressing: c.addressing };\n }),\n };\n}\n\ntype Sort = Array<{ key: string; desc: boolean }>;\n\n/** The door's `parseCollectionQuery`: the same bounds, the same 400s. */\nfunction parseQuery(params: URLSearchParams, c: { sort: string[]; pageSize: number }): { offset: number; limit: number; sort: Sort } | string {\n for (const name of params.keys()) {\n if (name === \"embed\") return \"embed is not available\";\n if (name === \"ref\" || name.startsWith(\"ref[\")) return \"ref filter is not available\";\n }\n const one = (name: string): string | undefined | null => {\n const all = params.getAll(name);\n return all.length === 0 ? undefined : all.length === 1 ? all[0] : null;\n };\n const rawOffset = one(\"offset\");\n if (rawOffset === null || (rawOffset !== undefined && !DIGITS.test(rawOffset))) return \"invalid offset\";\n const offset = rawOffset === undefined ? 0 : Number(rawOffset);\n if (offset > MAX_OFFSET) return \"offset too large\";\n const rawLimit = one(\"limit\");\n if (rawLimit === null || (rawLimit !== undefined && !DIGITS.test(rawLimit))) return \"invalid limit\";\n const limit = Math.min(MAX_LIMIT, Math.max(1, rawLimit === undefined ? c.pageSize : Number(rawLimit)));\n const rawSort = one(\"sort\");\n if (rawSort === null) return \"invalid sort\";\n const terms =\n rawSort !== undefined ? rawSort.split(\",\") : c.sort.length > 0 ? [...c.sort] : [`-${PUBLISHED_AT}`];\n if (terms.length > MAX_SORT_KEYS) return \"invalid sort\";\n const allowed = new Set([PUBLISHED_AT, ...c.sort.map((s) => s.replace(/^-/, \"\"))]);\n const sort: Sort = [];\n for (const term of terms) {\n const m = SORT_TERM.exec(term);\n if (!m || !allowed.has(m[2]) || sort.some((s) => s.key === m[2])) return \"invalid sort\";\n sort.push({ key: m[2], desc: m[1] === \"-\" });\n }\n return { offset, limit, sort };\n}\n\n/** jsonb-like order within a type (strings < numbers < booleans); a missing value sorts last. */\nfunction compareRecords(sort: Sort) {\n const rank = (v: unknown) => (typeof v === \"string\" ? 0 : typeof v === \"number\" ? 1 : 2);\n const valueOf = (r: PublicRecord, key: string) => (key === PUBLISHED_AT ? r.publishedOn : r.properties[key]);\n return (a: PublicRecord, b: PublicRecord): number => {\n for (const { key, desc } of sort) {\n const va = valueOf(a, key);\n const vb = valueOf(b, key);\n if (va === undefined || vb === undefined) {\n if (va !== vb) return va === undefined ? 1 : -1;\n continue;\n }\n let d = rank(va) - rank(vb);\n if (d === 0) d = va < vb ? -1 : va > vb ? 1 : 0;\n if (d !== 0) return desc ? -d : d;\n }\n if (a.publishedOn !== b.publishedOn) return a.publishedOn < b.publishedOn ? 1 : -1;\n return a.publicId < b.publicId ? -1 : a.publicId > b.publicId ? 1 : 0;\n };\n}\n\n/** 200 with a weak ETag, or 304 when If-None-Match already holds it. */\nfunction cached(view: unknown, ifNoneMatch: string | null): Response {\n const etag = weakEtag(view);\n if (etagMatches(ifNoneMatch, etag)) {\n return new Response(null, { status: 304, headers: { ETag: etag, \"Cache-Control\": \"no-cache\" } });\n }\n return json(200, view, { ETag: etag });\n}\n\nfunction siteDoor(site: MockSite, rest: string[], params: URLSearchParams, ifNoneMatch: string | null): Response {\n if (rest.length === 0) return cached(manifest(site), ifNoneMatch);\n if (rest[0] !== \"collections\" || rest.length > 3 || !Object.hasOwn(site.collections, rest[1])) {\n return json(404, NOT_FOUND);\n }\n const c = site.collections[rest[1]];\n if (rest.length === 2) {\n const q = parseQuery(params, c);\n if (typeof q === \"string\") return json(400, { error: q });\n const sorted = [...c.records].sort(compareRecords(q.sort));\n const page: PublicCollectionPage = {\n items: sorted.slice(q.offset, q.offset + q.limit).map(summary),\n total: sorted.length,\n offset: q.offset,\n limit: q.limit,\n };\n return cached(page, ifNoneMatch);\n }\n const address = rest[2];\n const byPublicId = PUBLIC_ID_RE.test(address);\n if (!byPublicId && !(address.length <= SLUG_MAX_LENGTH && SLUG_RE.test(address))) return json(404, NOT_FOUND);\n const record = c.records.find((r) => (byPublicId ? r.publicId === address : r.slug === address));\n if (!record) return json(404, NOT_FOUND);\n if (params.has(\"embed\")) return json(400, { error: \"embed is not available\" });\n return cached(record, ifNoneMatch);\n}\n\n/** The door's 422 for answers that do not satisfy the form (required, enum). */\nfunction invalidKeys(form: PublicForm, body: unknown): string[] {\n const fields = (body as { fields?: unknown } | null)?.fields;\n if (typeof fields !== \"object\" || fields === null) return [];\n const answers = fields as Record<string, unknown>;\n return form.fields\n .filter((f) => {\n const v = answers[f.key];\n if (v === undefined || v === \"\" || v === null) return f.required === true;\n if (f.type === \"boolean\") return typeof v !== \"boolean\" || (f.required === true && v !== true);\n const allowed = f.constraints?.enum;\n return allowed !== undefined && !allowed.includes(String(v));\n })\n .map((f) => f.key);\n}\n\nexport function createMockPod(options: MockPodOptions = {}): MockPod {\n const forms = options.forms ?? { [MOCK_TOKENS.form]: MOCK_FORM };\n const shares = options.shares ?? { [MOCK_TOKENS.share]: MOCK_SHARE, [MOCK_TOKENS.htmlShare]: MOCK_HTML_SHARE };\n const sites = options.sites ?? { [MOCK_TOKENS.site]: MOCK_SITE };\n const requests: MockRequest[] = [];\n const submissions: MockSubmission[] = [];\n\n const mockFetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const request = typeof input === \"object\" && \"method\" in input ? input : null;\n const url = new URL(typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url);\n const method = (init?.method ?? request?.method ?? \"GET\").toUpperCase();\n const headers: Record<string, string> = {};\n new Headers(init?.headers ?? request?.headers).forEach((value, name) => {\n headers[name.toLowerCase()] = value;\n });\n const credentials = init?.credentials ?? request?.credentials;\n requests.push({ method, url: url.href, headers, credentials });\n\n // What a browser does against the real doors (`Access-Control-Allow-Origin: *`).\n if (credentials === \"include\") throw new TypeError(\"Failed to fetch: credentialed request to a public door\");\n if (options.browser) {\n const preflighted = Object.keys(headers).filter((h) => !SAFELISTED.has(h) && !PREFLIGHT_ALLOWED.has(h));\n if (preflighted.length > 0) throw new TypeError(`Failed to fetch: preflight refuses ${preflighted.join(\", \")}`);\n }\n\n const m = url.pathname.match(/^\\/api\\/hub\\/public\\/(forms|shares|sites)\\/(.+)$/);\n if (!m) return json(404, NOT_FOUND);\n let segments: string[];\n try {\n segments = m[2].split(\"/\").map(decodeURIComponent);\n } catch {\n return json(404, NOT_FOUND);\n }\n const [token, ...rest] = segments;\n const failed = failure(token);\n if (failed === \"reject\") throw new TypeError(\"Failed to fetch: mock pod unreachable\");\n if (failed) return failed;\n\n const door = m[1];\n if (door === \"forms\" && method === \"POST\" && rest.length === 0) {\n let body: unknown = null;\n try {\n body = JSON.parse(typeof init?.body === \"string\" ? init.body : \"null\");\n } catch {\n body = null;\n }\n const form = Object.hasOwn(forms, token) ? forms[token] : undefined;\n const invalid = form ? invalidKeys(form, body) : [];\n const status = invalid.length > 0 ? 422 : 202;\n submissions.push({ token, body, status });\n return status === 422 ? json(422, { received: false, invalid }) : json(202, { received: true });\n }\n if (method !== \"GET\") return json(404, NOT_FOUND);\n if (door === \"forms\" && rest.length === 0 && Object.hasOwn(forms, token)) return json(200, forms[token]);\n if (door === \"shares\" && rest.length === 0 && Object.hasOwn(shares, token)) return json(200, shares[token]);\n if (door === \"sites\" && Object.hasOwn(sites, token)) {\n return siteDoor(sites[token], rest, url.searchParams, headers[\"if-none-match\"] ?? null);\n }\n return json(404, NOT_FOUND);\n };\n\n return {\n podUrl: MOCK_POD_URL,\n fetch: mockFetch as typeof fetch,\n requests,\n submissions,\n reset() {\n requests.length = 0;\n submissions.length = 0;\n },\n };\n}\n"],"mappings":"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","names":["failure","json"]}
1
+ {"version":3,"sources":["../src/testing/fixtures.ts","../src/testing/roles.ts","../src/testing/auth-server.ts","../src/testing/seed.ts","../src/testing/cloud.ts","../src/testing/index.ts"],"sourcesContent":["/**\n * Demo data for the mock pod. Shapes are the `@synap-core/sdk/public` wire\n * types, so a fixture that drifts from the contract fails to compile.\n */\nimport type { PublicForm, PublicRecord, PublicShare } from \"../public/client\";\n\nexport const MOCK_FORM: PublicForm = {\n title: \"Get in touch\",\n fields: [\n { key: \"name\", label: \"Name\", type: \"text\", required: true, constraints: { maxLength: 120 } },\n { key: \"email\", label: \"Email\", type: \"email\", required: true },\n {\n key: \"topic\",\n label: \"Topic\",\n type: \"enum\",\n constraints: { enum: [\"Sales\", \"Support\", \"Partnership\"] },\n },\n { key: \"message\", label: \"Message\", type: \"richtext\", help: \"A few lines is plenty.\" },\n ],\n successMessage: \"Thanks — we received your message.\",\n honeypotField: \"hp\",\n ticket: \"mock-ticket\",\n minSubmitMs: 0,\n captcha: { required: false },\n};\n\nexport const MOCK_SHARE: PublicShare = {\n resourceType: \"entity\",\n title: \"Launch notes\",\n properties: { status: \"open\", owner: \"Ada\", featured: true },\n body: {\n format: \"markdown\",\n content: [\n \"# Launch notes\",\n \"\",\n \"This page is a **published snapshot** from a Synap pod.\",\n \"\",\n \"- Read the [Synap docs](https://synap.live)\",\n \"- Links other than http, https and mailto render as plain text: [bad](javascript:alert(1))\",\n \"\",\n \"<script>raw HTML is shown as text, never run</script>\",\n ].join(\"\\n\"),\n },\n publishedOn: \"2026-09-27\",\n};\n\n/**\n * A published HTML document (an estimate), as the pod serves an `html` body: a\n * page renders it only inside `<iframe sandbox=\"\" srcdoc>`, so the script below\n * never runs.\n */\nexport const MOCK_HTML_SHARE: PublicShare = {\n resourceType: \"entity\",\n title: \"Estimate for Northwind\",\n properties: { total: \"4 800 €\", validUntil: \"2026-11-30\" },\n body: {\n format: \"html\",\n content: [\n \"<!doctype html>\",\n '<html lang=\"en\"><head><meta charset=\"utf-8\"><title>Estimate</title>',\n \"<style>body{font-family:Georgia,serif;max-width:40rem;margin:2rem auto;line-height:1.5}td{padding:.25rem .75rem}</style>\",\n \"</head><body>\",\n \"<h1>Estimate for Northwind</h1>\",\n \"<table><tr><td>Discovery workshop</td><td>1 200 €</td></tr><tr><td>Build</td><td>3 600 €</td></tr></table>\",\n \"<p><strong>Total: 4 800 €</strong></p>\",\n \"<script>document.body.textContent = 'scripts never run in a sandboxed frame'</script>\",\n \"</body></html>\",\n ].join(\"\"),\n },\n publishedOn: \"2026-10-22\",\n};\n\n/** One collection of a mock site: its door config and its live records. */\nexport interface MockCollection {\n /** Default sort keys (`-` = descending); also the sort keys the door accepts. */\n sort: string[];\n pageSize: number;\n addressing: \"slug\" | \"publicId\";\n records: PublicRecord[];\n}\n\n/** A mock published site. The manifest is derived from it (counts included). */\nexport interface MockSite {\n title?: string;\n description?: string;\n publishedOn: string;\n collections: Record<string, MockCollection>;\n}\n\n/** A public id of the door's shape (`p_` + 16 base62), deterministic. */\nfunction publicId(prefix: string, n: number): string {\n return `p_${prefix}${String(n).padStart(16 - prefix.length, \"0\")}`;\n}\n\nfunction slugify(s: string): string {\n return s\n .normalize(\"NFKD\")\n .replace(/[̀-ͯ]/g, \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 96);\n}\n\nconst PAPER_TITLES = [\n \"Sparse graphs at scale\",\n \"Learning to rank, revisited\",\n \"A note on causal tracing\",\n \"Small models, long contexts\",\n \"Evaluating retrieval honestly\",\n \"Robust tokenisation\",\n \"Graphs that forget\",\n \"Calibration under shift\",\n \"Latent space cartography\",\n \"Proofs as programs, again\",\n \"Cheap uncertainty\",\n \"Résumé of a decade\",\n];\nconst VENUES = [\"NeurIPS\", \"ICML\", \"ACL\", \"ICLR\"];\n\nconst PAPERS: PublicRecord[] = PAPER_TITLES.map((title, i) => ({\n collection: \"paper\",\n publicId: publicId(\"paper\", i + 1),\n slug: slugify(title),\n title,\n properties: {\n year: 2026 - (i % 5),\n venue: VENUES[i % VENUES.length],\n open: i % 3 !== 0,\n },\n publishedOn: `2026-09-${String(28 - i).padStart(2, \"0\")}`,\n body: i % 4 === 3 ? null : { format: \"markdown\", content: `# ${title}\\n\\nAbstract of **${title}**.` },\n}));\n\nconst PEOPLE: PublicRecord[] = [\"Ada Lovelace\", \"Alan Turing\", \"Grace Hopper\"].map((name, i) => ({\n collection: \"person\",\n publicId: publicId(\"person\", i + 1),\n slug: null,\n title: name,\n properties: { name, role: i === 0 ? \"Lead\" : \"Researcher\" },\n publishedOn: \"2026-09-01\",\n body: null,\n}));\n\n/**\n * The demo site: `paper` (12 records, 5 per page, by slug: pagination),\n * `person` (by public id), `event` (nothing published: the empty state).\n */\nexport const MOCK_SITE: MockSite = {\n title: \"Demo lab\",\n description: \"What the lab publishes\",\n publishedOn: \"2026-09-01\",\n collections: {\n paper: { sort: [\"-year\"], pageSize: 5, addressing: \"slug\", records: PAPERS },\n person: { sort: [\"name\"], pageSize: 20, addressing: \"publicId\", records: PEOPLE },\n event: { sort: [], pageSize: 10, addressing: \"slug\", records: [] },\n },\n};\n","/**\n * The mock's ONE role model is `facets` (./seed.ts `MockSeedFacet`). The\n * deprecated `seedRoles` shorthand is desugared into it here, once, by\n * `parseMockPodSeed` and by `createMockAuthServer` for `options.entities`, so\n * nothing downstream reads `seedRoles`. Not exported from `@synap-core/sdk/testing`.\n */\nimport type { MockSeedFacet } from \"./seed\";\n\n/**\n * `row` with its `seedRoles` turned into `facets` (a generated `facetId`, no\n * overlay). A role stated in both (same slug, same space) is a TypeError\n * naming the entity: one fact, one place, never a silent merge.\n */\nexport function desugarSeedRoles(row: Record<string, unknown>, at: string): Record<string, unknown> {\n if (!Array.isArray(row.seedRoles)) return row;\n const { seedRoles, ...rest } = row;\n const facets = Array.isArray(row.facets) ? (row.facets as MockSeedFacet[]) : [];\n const shorthand = (seedRoles as Array<{ profileSlug?: unknown; workspaceId?: unknown }>)\n .filter((r) => typeof r?.profileSlug === \"string\" && typeof r.workspaceId === \"string\")\n .map((r, i): MockSeedFacet => ({ facetId: `seedrole_${String(row.id)}_${i}`, slug: r.profileSlug as string, workspaceId: r.workspaceId as string }));\n for (const r of shorthand) {\n if (facets.some((f) => f?.slug === r.slug && f.workspaceId === r.workspaceId)) {\n throw new TypeError(`${at} (\"${String(row.id)}\"): the role \"${r.slug}\" in ${r.workspaceId} is in both facets and seedRoles; keep it in facets only`);\n }\n }\n return { ...rest, facets: [...facets, ...shorthand] };\n}\n","/**\n * A mock pod for pod-app sign-in: its OAuth authorization server (RFC 8414\n * metadata, /authorize as a function standing in for the consent screen,\n * /token, /revoke) and a few Hub REST doors behind the Bearer token. Inject\n * `fetch` into the REAL `@synap-core/sdk/connect` (`createPodAppAuth({ fetch })`)\n * so everything above the wire is the production path. No network.\n *\n * Wire behaviour mirrors synap-backend `routers/oauth/routes.ts` for a CIMD\n * client: `iss` on every authorization answer (RFC 9207), PKCE S256 checked at\n * /token, single-use codes bound to client_id + redirect_uri + resource, the\n * token response's `synap_grant` / `synap_user`. Refresh mirrors the pod's\n * (`routers/oauth/refresh.ts`): rotating and single-use, 30 days from issue;\n * a token presented AGAIN after its use is a reuse that revokes its whole\n * family AND the live access key; a new code ends the client's older\n * families; /revoke with a refresh token kills its family and access key.\n * The reuse grace: within 30 s of its use, a spent token presented\n * again with its own client_id gets the SAME pair its first use got (the\n * successor refresh token and the live key, `expires_in` = what that key has\n * left), as long as the successor is unused; past it, a reuse.\n * `refresh: false` is a pod without refresh tokens (no refresh_token at all).\n *\n * Hub REST: `GET /users/me`, `GET /entities` (an ARRAY of entities, as the pod\n * answers; the seeds plus what applied writes created), `GET /proposals`\n * (`{ proposals, limit, offset, total, hasMore }`, rows only in spaces where\n * the token holds `proposal.read`, as the pod's grant clause; `proposalIds`),\n * governed writes. 1.5, from `seed` (one JSON shape, ./seed.ts):\n * `GET /entities/:id` (404 with an empty body, as the pod), `GET\n * /entities/:id/connections` (`{ connections, counts }`: seeded relations and\n * the sessions about it), `GET /documents/:id` (`{ document }`), `GET\n * /focus-sessions` (an ARRAY; `workspaceId` or `projectId` required; status,\n * limit 1-50, lens, kind, subjectEntityId), `POST /proposals/:id/approve`.\n * 1.5.1, roles (seed `entities[].facets`; `seedRoles` is desugared into them): the\n * reach rule (a granted space's rows, plus the pod-wide rows with a role in\n * one); `GET /entities` filters by `facetSlug` (and a `profileSlug` naming a\n * role), drops the pod-wide rows of a workspace lens on `includePodWide=false`,\n * and with `includeFacets=true` puts `facetSlugs` + `facets` on the rows that\n * wear a visible one; `GET /entities/:id/facets` (`{ facets: [{ facet,\n * profile, effectiveProperties }] }`). The token sees a facet as a member of\n * a granted space does (its seed `workspaceId`), never another. A role is known by its slug only: no 404 for an\n * undeclared `facetSlug`, a synthetic profile id, `effectiveProperties` empty.\n *\n * Who the token acts as: `actsAs: \"person\"` answers\n * `synap_acts_as: \"person\"`, applies writes directly (unless `writeMode`\n * says otherwise) and lets the token approve where it holds\n * `proposal.approve`; `\"agent\"` answers `\"agent\"`; omitted, the field is not\n * sent (a pod that does not name it) and the token is an agent's. An agent's approve is\n * refused 403, as the pod's `rejectAgentReviewer`.\n *\n * mock.authorize(authorizeUrl) → the callback URL (approved)\n * mock.authorize(authorizeUrl, { deny: true }) → error=access_denied\n * mock.authorize(authorizeUrl, { iss: \"https://evil.example\" }) → a mix-up attempt\n * mock.loseNextRefreshRace() → the next redeem is a concurrent loser that found no successor (refused, no revoke)\n * mock.redeemElsewhere(t) → another app instance rotated t (presenting it within 30 s gets that pair)\n * mock.consumeRefreshToken(t) → the token was used elsewhere with no successor (presenting it is a reuse)\n * mock.revokeAll() → the person removed the app in their pod\n * mock.revokeAccessKeys() → a narrow or a pod-side \"Revoke key\": the live keys stop, the connection (its refresh token) lives\n */\nimport { pkceChallenge, randomToken } from \"../connect/encoding\";\nimport type { PodActsAs, PodGrant, PodUser } from \"../connect/types\";\nimport { desugarSeedRoles } from \"./roles\";\nimport type { MockPodSeed, MockSeedDocument, MockSeedFacet, MockSeedRelation, MockSeedSession } from \"./seed\";\n\n/** A placeholder pod origin; never contacted. */\nexport const MOCK_AUTH_ISSUER = \"https://pod.mock-synap.test\";\n\n/** Space -> readable kinds (null = all), what a token's `entity.*.read` grant rows add up to. */\ntype ReadSpaces = ReadonlyMap<string, ReadonlySet<string> | null>;\n\nexport const MOCK_GRANT: PodGrant[] = [\n { permission: \"entity.post.read\", workspaceId: \"ws_mock_studio\", workspaceName: \"Studio\" },\n { permission: \"entity.post.create\", workspaceId: \"ws_mock_studio\", workspaceName: \"Studio\" },\n];\n\n/** The pod's step-up refusal text (backend `STEP_UP_REQUIRED_MESSAGE`). */\nconst STEP_UP_MESSAGE = \"Confirm it's you before changing who or what can reach this pod.\";\n\nexport const MOCK_USER: PodUser = { id: \"user_mock_ada\", name: \"Ada Lovelace\" };\n\nexport type MockHubFailure =\n | \"rate_limited\"\n | \"forbidden\"\n | \"door_unsupported\"\n /** 403 `{ error: <the pod's step-up message> }`: a stale device at a credential door (the Hub REST body has no reasonCode). */\n | \"step_up_required\"\n /** 409 problem `CP_ACCOUNT_EMAIL_REQUIRED` (Control Plane: no verified email). */\n | \"email_unverified\"\n /** 409 problem `FEDERATED_APPLICATION_ORIGIN_INSECURE` (Control Plane: an app origin that is not HTTPS). */\n | \"origin_insecure\"\n | \"unreachable\"\n | \"server\"\n | \"unavailable\";\n\nexport interface MockAuthServerOptions {\n issuer?: string;\n /** Issue rotating refresh tokens. Default true; false = a pod without refresh tokens. */\n refresh?: boolean;\n /** Default 3600 (the pod's 1 h). */\n accessTtlSec?: number;\n /** Default 30 days. */\n refreshIdleSec?: number;\n /** Send `refresh_token_expires_in` with each refresh token. Default false (the pod does not say). */\n advertiseRefreshExpiry?: boolean;\n /** The reuse grace, seconds. Default 30 (the pod's); 0 = off (a pod without the grace). */\n refreshGraceSec?: number;\n /**\n * `synap_app` on token responses: the connection's id and its page on the\n * pod console. Default `MOCK_APP`; null = a pod that does not send it.\n */\n app?: { id: string; manageUrl: string | null } | null;\n /** Entities `GET /entities` answers (with `workspaceId` / `profileSlug` filters). */\n entities?: Array<Record<string, unknown>>;\n grant?: PodGrant[];\n user?: PodUser;\n /** Override or remove (undefined) metadata fields: a pod too old, a lying issuer. */\n metadata?: Record<string, unknown>;\n /**\n * Hub writes: \"proposed\" (ask-first, the default for an agent token) or\n * \"applied\" (the default for `actsAs: \"person\"`).\n */\n writeMode?: \"proposed\" | \"applied\";\n /**\n * `synap_acts_as` on token responses. Omitted = not sent (a pod that does\n * not name it; the SDK reads an agent connection).\n */\n actsAs?: PodActsAs;\n /**\n * A Synap app's device starts STALE: `POST /proposals/:id/approve` is refused\n * (403 `{ error: <step-up message> }`, the Hub REST shape) until the person\n * re-confirms at the pod: `/authorize?prompt=login`, the code redeemed with the\n * device's refresh token as `synap_device_refresh_token`. Needs `actsAs: \"person\"`.\n * `expireStepUp()` makes it stale again (the 15-minute window).\n */\n requireStepUp?: boolean;\n /**\n * The pod's data as one JSON shape (`parseMockPodSeed`). `seed.entities` come\n * before `entities`; `seed.spaces` put a `templateSlug` on the grant rows of\n * those spaces.\n */\n seed?: MockPodSeed;\n /** Hub paths (after /api/hub) that answer one failure. */\n failures?: Record<string, MockHubFailure>;\n now?: () => number;\n}\n\nexport interface MockAuthRequest {\n method: string;\n url: string;\n /** Lower-cased header names. */\n headers: Record<string, string>;\n /** The form body of a /token or /revoke call. */\n form: Record<string, string> | null;\n}\n\nexport interface AuthorizeDecision {\n /** The person said no. */\n deny?: boolean;\n /** Override `iss` on the answer (null = omit it): a mix-up attack. */\n iss?: string | null;\n /** Override `state` on the answer: a forged answer. */\n state?: string;\n}\n\n/** A proposal a governed write filed (`GET /proposals` lists the pending ones). */\nexport interface MockProposal {\n id: string;\n proposalType: string;\n targetType: string;\n targetId: string | null;\n status: \"pending\" | \"approved\" | \"rejected\";\n workspaceId: string | null;\n createdAt: string;\n correlationId: string | null;\n sessionId: string | null;\n agentUserId: string | null;\n summary?: string;\n}\n\n/** The connection's `synap_app` the mock pod answers by default (backend `appTokenResponse`). */\nexport const MOCK_APP = { id: \"app_mock_studio\", manageUrl: \"https://pod-admin.mock-synap.test/apps/app_mock_studio\" };\n\n/** The app's agent on the mock pod: who files its proposals. */\nexport const MOCK_APP_AGENT_ID = \"agent_mock_app\";\n\nexport interface MockAuthServer {\n issuer: string;\n fetch: typeof fetch;\n requests: MockAuthRequest[];\n /** Hub writes seen, in order. */\n writes: Array<{ method: string; path: string; body: unknown }>;\n /** Proposals: the seeded ones, then those filed by proposed writes, in order. */\n proposals: MockProposal[];\n /** Proposals approved through `POST /proposals/:id/approve`, in order. */\n approvals: string[];\n /** The person approved or rejected one: it leaves the pending list. */\n settleProposal(id: string, status: \"approved\" | \"rejected\"): void;\n /** Another instance of the app rotated `token` (its own refresh): returns the pair the pod answered it. */\n redeemElsewhere(token: string): Promise<{ access_token: string; refresh_token: string; expires_in: number }>;\n /** Refresh redeems answered within the reuse grace (the same pair again). */\n graceAnswers: number;\n /** Stand-in for the consent screen: validates the request like /authorize, returns where the pod redirects. */\n authorize(authorizeUrl: string, decision?: AuthorizeDecision): string;\n /** Mark a refresh token used elsewhere: presenting it now is a REUSE (family + live key revoked). */\n consumeRefreshToken(token: string): void;\n /** The pod now says `synap_acts_as: v` (null = says nothing): the app left, or joined, the Synap list. */\n setActsAs(v: PodActsAs | null): void;\n /** The device's last real sign-in is older than the step-up window. */\n expireStepUp(): void;\n /** The next refresh redeem loses a concurrent race: invalid_grant, nothing revoked. */\n loseNextRefreshRace(): void;\n /** Refresh-token redeems that were reuses (each revoked a family). */\n reuses: number;\n /** The person revoked the app: every token stops working. */\n revokeAll(): void;\n /**\n * The live access keys stop working, the refresh tokens do not: what a\n * narrow (the slot's key is revoked at once) or a pod-side \"Revoke key\"\n * does. The next refresh mints a new key.\n */\n revokeAccessKeys(): void;\n /** Live (unrevoked) refresh tokens. */\n liveRefreshTokens(): string[];\n reset(): void;\n}\n\ninterface CodeRow {\n clientId: string;\n redirectUri: string;\n challenge: string;\n resource: string | null;\n scope: string[];\n /** `prompt=login` from a Synap app: its code re-confirms a device (and must come with its refresh token). */\n stepUp: boolean;\n}\n\ninterface AccessRow {\n expiresAt: number;\n revoked: boolean;\n family: string | null;\n scope: string[];\n}\n\ninterface RefreshRow {\n clientId: string;\n family: string;\n idleUntil: number;\n used: boolean;\n revoked: boolean;\n scope: string[];\n /** When it was spent, and the pair that use was answered (the grace re-answers it). */\n usedAt?: number;\n successor?: string;\n pairAccess?: string;\n}\n\nfunction json(status: number, body: unknown, headers: Record<string, string> = {}): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\", ...headers },\n });\n}\n\nfunction oauthError(error: string, description: string, status = 400): Response {\n return json(status, { error, error_description: description });\n}\n\nexport function createMockAuthServer(options: MockAuthServerOptions = {}): MockAuthServer {\n const issuer = options.issuer ?? MOCK_AUTH_ISSUER;\n const now = options.now ?? Date.now;\n const refresh = options.refresh ?? true;\n const accessTtl = options.accessTtlSec ?? 3600;\n const refreshIdle = options.refreshIdleSec ?? 30 * 24 * 3600;\n const grant = options.grant ?? MOCK_GRANT;\n const user = options.user ?? MOCK_USER;\n const codes = new Map<string, CodeRow>();\n const access = new Map<string, AccessRow>();\n const refreshTokens = new Map<string, RefreshRow>();\n const requests: MockAuthRequest[] = [];\n const writes: Array<{ method: string; path: string; body: unknown }> = [];\n const proposals: MockProposal[] = [];\n const seed = options.seed ?? {};\n // One role model: a seed is desugared by parseMockPodSeed; `entities` (and a seed built in code) here.\n const entities: Array<Record<string, unknown>> = [...(seed.entities ?? []), ...(options.entities ?? [])].map((e, i) =>\n desugarSeedRoles(e, `entities[${i}]`),\n );\n const sessions: MockSeedSession[] = [...(seed.sessions ?? [])];\n const documents: MockSeedDocument[] = [...(seed.documents ?? [])];\n const relations: MockSeedRelation[] = [...(seed.relations ?? [])];\n const templateOf = new Map((seed.spaces ?? []).filter((sp) => sp.templateSlug).map((sp) => [sp.id, sp.templateSlug!]));\n const approvals: string[] = [];\n const seededAt = new Date(now()).toISOString();\n\n /** The roles (facets) an entity wears: the seed's `facets` (`seedRoles` was desugared into them). */\n const rolesOf = (e: Record<string, unknown>): MockSeedFacet[] =>\n Array.isArray(e.facets) ? (e.facets as MockSeedFacet[]).filter((f) => typeof f?.slug === \"string\") : [];\n /**\n * What the token's grant lets it read of an entity (the pod's grant clause):\n * a row of a granted space, or a pod-wide row (`workspaceId` null) with a live\n * role in one. The pod sends no role field on an entity row, so the mock takes\n * its roles as SEED input (`facets`) and answers them only when asked.\n */\n function readableEntity(e: Record<string, unknown>, spaces: ReadSpaces, only?: string | null): boolean {\n if (typeof e.workspaceId === \"string\" && kindReadable(e, spaces, e.workspaceId) && (!only || e.workspaceId === only)) return true;\n // A pod-wide row is reached by any role in the space; a row of ANOTHER space only by a role stamped in this one.\n return facetsOf(e, spaces, only ?? undefined).some((f) => e.workspaceId == null || !f.sharedRole);\n }\n /**\n * The roles of `e` a read sees: what a member of a granted space sees\n * (backend `facetVisibilityConditions` under the token's grant), i.e. a role\n * whose seed space is granted; a workspace lens sees that space's roles only.\n */\n const facetsOf = (e: Record<string, unknown>, spaces: ReadSpaces, lens?: string): MockSeedFacet[] =>\n rolesOf(e).filter((f) => typeof f.workspaceId === \"string\" && kindReadable(e, spaces, f.workspaceId) && (lens === undefined || f.workspaceId === lens));\n /** backend `FacetRowAnnotation`: what `includeFacets=true` puts on a row. */\n const facetRow = (f: MockSeedFacet) => ({ facetId: f.facetId, slug: f.slug, properties: f.properties ?? {}, status: f.status ?? null });\n /** A row as the Hub answers it (`entityToWire`): roles ride on it only when asked. */\n const entityWire = (e: Record<string, unknown>): Record<string, unknown> => {\n const { facets: _facets, facetSlugs: _facetSlugs, ...wire } = e;\n return wire;\n };\n /**\n * Space -> the kinds the token reads there (null = every kind), as the pod's\n * kindClause: `entity.<kind>.read` narrows to that kind; `entity.read` and\n * `entity.*.read` read all.\n */\n const readSpaces = (scope: readonly string[]): ReadSpaces => {\n const out = new Map<string, Set<string> | null>();\n for (const g of grant) {\n const m = /^entity\\.(?:(.+)\\.)?read$/.exec(g.permission);\n if (!m || !scope.includes(g.permission)) continue;\n const kind = m[1];\n if (kind === undefined || kind === \"*\") out.set(g.workspaceId, null);\n else if (out.get(g.workspaceId) !== null) out.set(g.workspaceId, (out.get(g.workspaceId) ?? new Set<string>()).add(kind));\n else continue;\n }\n return out;\n };\n /** Whether the token reads rows of `e`'s kind in `space`. */\n const kindReadable = (e: Record<string, unknown>, spaces: ReadSpaces, space: string): boolean => {\n if (!spaces.has(space)) return false;\n const kinds = spaces.get(space);\n return kinds === null || kinds === undefined ? kinds === null : kinds.has(String(e.profileSlug ?? e.type ?? \"\"));\n };\n for (const p of seed.proposals ?? []) {\n proposals.push({\n proposalType: \"create\",\n targetType: \"entity\",\n targetId: null,\n status: \"pending\",\n workspaceId: null,\n createdAt: seededAt,\n correlationId: null,\n sessionId: null,\n agentUserId: null,\n ...p,\n });\n }\n // What the pod says about the app, re-judged on every token response (`setActsAs` moves it).\n let actsAs = options.actsAs;\n const writeMode = () => options.writeMode ?? (actsAs === \"person\" ? \"applied\" : \"proposed\");\n // A Synap app's device clock: stale until the person re-confirms at the pod (`requireStepUp`).\n let deviceFresh = !options.requireStepUp;\n const graceMs = (options.refreshGraceSec ?? 30) * 1000;\n const app = options.app === undefined ? MOCK_APP : options.app;\n let proposalSeq = 0;\n let graceAnswers = 0;\n\n const metadata = (): Record<string, unknown> => {\n const base: Record<string, unknown> = {\n issuer,\n authorization_endpoint: `${issuer}/authorize`,\n token_endpoint: `${issuer}/token`,\n registration_endpoint: `${issuer}/register`,\n revocation_endpoint: `${issuer}/revoke`,\n revocation_endpoint_auth_methods_supported: [\"none\"],\n response_types_supported: [\"code\"],\n grant_types_supported: refresh ? [\"authorization_code\", \"refresh_token\"] : [\"authorization_code\"],\n code_challenge_methods_supported: [\"S256\"],\n token_endpoint_auth_methods_supported: [\"none\"],\n authorization_response_iss_parameter_supported: true,\n client_id_metadata_document_supported: true,\n };\n for (const [k, v] of Object.entries(options.metadata ?? {})) {\n if (v === undefined) delete base[k];\n else base[k] = v;\n }\n return base;\n };\n\n let loseNextRace = false;\n let reuses = 0;\n const revokeFamily = (family: string) => {\n for (const r of refreshTokens.values()) if (r.family === family) r.revoked = true;\n for (const a of access.values()) if (a.family === family) a.revoked = true;\n };\n\n /** The token response; `pair` re-answers an existing access key + refresh token (the grace). */\n const tokenBody = (scope: string[], clientId: string, family: string, pair?: { accessToken: string; refreshToken: string }) => {\n const accessToken = pair?.accessToken ?? `synap_hub_mock_${randomToken()}`;\n if (!pair) access.set(accessToken, { expiresAt: now() + accessTtl * 1000, revoked: false, family: refresh ? family : null, scope });\n const row = access.get(accessToken)!;\n const body: Record<string, unknown> = {\n access_token: accessToken,\n token_type: \"Bearer\",\n // As the pod: what the key has left, never an assumed hour.\n expires_in: Math.max(0, Math.floor((row.expiresAt - now()) / 1000)),\n scope: scope.join(\" \"),\n // Each grant row names its space's template when it came from one.\n synap_grant: grant\n .filter((g) => scope.includes(g.permission))\n .map((g) => (g.templateSlug || !templateOf.has(g.workspaceId) ? g : { ...g, templateSlug: templateOf.get(g.workspaceId)! })),\n synap_user: user,\n ...(app ? { synap_app: app } : {}),\n ...(actsAs ? { synap_acts_as: actsAs } : {}),\n };\n if (pair) {\n body.refresh_token = pair.refreshToken;\n if (options.advertiseRefreshExpiry) body.refresh_token_expires_in = Math.floor((refreshTokens.get(pair.refreshToken)!.idleUntil - now()) / 1000);\n } else if (refresh) {\n const refreshToken = randomToken();\n refreshTokens.set(refreshToken, { clientId, family, idleUntil: now() + refreshIdle * 1000, used: false, revoked: false, scope });\n body.refresh_token = refreshToken;\n if (options.advertiseRefreshExpiry) body.refresh_token_expires_in = refreshIdle;\n }\n return body;\n };\n\n async function token(form: Record<string, string>): Promise<Response> {\n if (form.grant_type === \"authorization_code\") {\n const row = form.code ? codes.get(form.code) : undefined;\n if (form.code) codes.delete(form.code); // claim first: a failed exchange burns the code\n if (!row) return oauthError(\"invalid_grant\", \"Invalid, expired, or already-redeemed authorization code\");\n if (row.clientId !== form.client_id) return oauthError(\"invalid_grant\", \"client_id does not match the code\");\n if (row.redirectUri !== form.redirect_uri) return oauthError(\"invalid_grant\", \"redirect_uri mismatch\");\n if (!form.code_verifier || (await pkceChallenge(form.code_verifier)) !== row.challenge) {\n return oauthError(\"invalid_grant\", \"PKCE verification failed\");\n }\n if (form.resource !== undefined && row.resource && form.resource !== row.resource) {\n return oauthError(\"invalid_target\", \"resource does not match the authorization request\");\n }\n // A Synap app's step-up (`routes.ts`): the code and the device's refresh token must agree.\n if (actsAs === \"person\" && row.stepUp !== Boolean(form.synap_device_refresh_token)) {\n return oauthError(\n \"invalid_grant\",\n row.stepUp\n ? \"This code re-confirms a device: send its refresh token as synap_device_refresh_token\"\n : \"This code signs a new device in; a re-confirmation asks with prompt=login\",\n );\n }\n if (row.stepUp) {\n const device = refreshTokens.get(form.synap_device_refresh_token!);\n if (!device || device.clientId !== row.clientId || device.used || device.revoked) {\n return oauthError(\"invalid_grant\", \"Invalid, expired, revoked or already-used refresh token\");\n }\n // The device keeps its family: its clock moves, nothing else is made or ended.\n device.used = true;\n deviceFresh = true;\n return json(200, tokenBody(row.scope, row.clientId, device.family));\n }\n // The latest connect wins: a new code ends this client's older families.\n for (const r of refreshTokens.values()) if (r.clientId === row.clientId) revokeFamily(r.family);\n return json(200, tokenBody(row.scope, row.clientId, randomToken()));\n }\n if (form.grant_type === \"refresh_token\") {\n if (!refresh) return oauthError(\"unsupported_grant_type\", 'Only grant_type \"authorization_code\" is supported');\n if (!form.refresh_token || !form.client_id) return oauthError(\"invalid_request\", \"refresh_token and client_id are required\");\n const row = refreshTokens.get(form.refresh_token);\n if (!row || row.clientId !== form.client_id || row.revoked) {\n return oauthError(\"invalid_grant\", \"Invalid, expired, revoked or already-used refresh token\");\n }\n if (row.used) {\n // The same pair again, inside the grace, while the successor is unused and its key lives.\n const successor = row.successor ? refreshTokens.get(row.successor) : undefined;\n const key = row.pairAccess ? access.get(row.pairAccess) : undefined;\n const inGrace = graceMs > 0 && row.usedAt !== undefined && now() - row.usedAt < graceMs;\n if (inGrace && successor && !successor.used && !successor.revoked && key && !key.revoked && key.expiresAt > now()) {\n graceAnswers++;\n return json(200, tokenBody(row.scope, row.clientId, row.family, { accessToken: row.pairAccess!, refreshToken: row.successor! }));\n }\n reuses++;\n revokeFamily(row.family);\n return oauthError(\"invalid_grant\", \"Invalid, expired, revoked or already-used refresh token\");\n }\n if (row.idleUntil <= now()) return oauthError(\"invalid_grant\", \"Invalid, expired, revoked or already-used refresh token\");\n if (loseNextRace) {\n loseNextRace = false;\n return oauthError(\"invalid_grant\", \"Invalid, expired, revoked or already-used refresh token\");\n }\n row.used = true;\n row.usedAt = now();\n // One live key per connection: the rotation retires the family's older keys.\n for (const a of access.values()) if (a.family === row.family) a.revoked = true;\n const body = tokenBody(row.scope, row.clientId, row.family);\n row.successor = body.refresh_token as string;\n row.pairAccess = body.access_token as string;\n return json(200, body);\n }\n return oauthError(\"unsupported_grant_type\", \"Unsupported grant_type\");\n }\n\n /** A focus-session row as the list door answers it: the table's columns (defaults filled), `triage`, `kind`. */\n const sessionRow = (s: MockSeedSession): Record<string, unknown> => ({\n workspaceId: null,\n projectId: null,\n userId: user.id,\n correlationId: null,\n title: null,\n goal: \"\",\n status: \"active\",\n templateId: null,\n expectedOutputs: [],\n channelId: null,\n progress: null,\n currentStage: null,\n agentIds: [],\n closedAt: null,\n verificationReport: null,\n metadata: {},\n startedAt: seededAt,\n createdAt: seededAt,\n updatedAt: seededAt,\n kind: \"work\",\n triage: { pending: false, acceptedAt: null, acceptedBy: null },\n ...s,\n });\n\n /** The seeded read doors (1.5); null when `path` is none of them. */\n function readSeeded(path: string, query: URLSearchParams, scope: readonly string[]): Response | null {\n const spaces = readSpaces(scope);\n const conn = /^\\/entities\\/([^/]+)\\/connections$/.exec(path);\n if (conn) {\n const id = decodeURIComponent(conn[1]);\n const ws = query.get(\"workspaceId\") ?? undefined;\n const limit = Math.min(Math.max(Number(query.get(\"limit\") ?? 50) || 50, 1), 200);\n const inLens = (e: Record<string, unknown>) => !ws || e.workspaceId === ws || e.workspaceId == null;\n const connections: Array<Record<string, unknown>> = [];\n const graph = relations\n .filter((r) => r.sourceEntityId === id || r.targetEntityId === id)\n .sort((a, b) => String(b.createdAt ?? \"\").localeCompare(String(a.createdAt ?? \"\")))\n .slice(0, limit);\n for (const r of graph) {\n const outgoing = r.sourceEntityId === id;\n const otherId = outgoing ? r.targetEntityId : r.sourceEntityId;\n const other = entities.find((e) => e.id === otherId);\n // As the pod: an edge whose far end is gone or out of the lens is not a neighbour.\n if (!other || !inLens(other) || !readableEntity(other, spaces)) continue;\n // An edge between two pod-wide records is pod-wide (owner-only): not readable by a space-scoped app.\n const self = entities.find((e) => e.id === id);\n if (self && self.workspaceId == null && other.workspaceId == null) continue;\n connections.push({\n entityId: otherId,\n // relations.ts: the raw row plus its role slugs under the read's facet lens (a 1.5.0 seed's own facetSlugs otherwise).\n entity: {\n ...entityWire(other),\n type: other.profileSlug ?? other.type ?? null,\n facetSlugs: rolesOf(other).length > 0 ? facetsOf(other, spaces, ws).map((f) => f.slug) : (other.facetSlugs ?? []),\n },\n label: r.type,\n direction: outgoing ? \"outgoing\" : \"incoming\",\n source: \"graph\",\n relationId: r.id,\n relationType: r.type,\n createdAt: r.createdAt ?? null,\n });\n }\n for (const s of sessions.filter((x) => x.subjectEntityId === id).slice(0, limit)) {\n const row = sessionRow(s);\n connections.push({\n entityId: s.id,\n entity: null,\n label: (row.title as string | null) || (row.goal as string),\n direction: \"incoming\",\n source: \"focus_session\",\n focusSessionId: s.id,\n focusSessionGoal: row.goal,\n focusSessionStatus: row.status,\n focusSessionWorkspaceId: row.workspaceId,\n createdAt: row.createdAt,\n });\n }\n const n = (source: string) => connections.filter((c) => c.source === source).length;\n return json(200, {\n connections,\n counts: { total: connections.length, graph: n(\"graph\"), structural: n(\"property\"), threads: n(\"thread\"), contextChannels: n(\"context_channel\"), focusSessions: n(\"focus_session\") },\n });\n }\n const entity = /^\\/entities\\/([^/]+)$/.exec(path);\n if (entity) {\n const found = entities.find((e) => e.id === decodeURIComponent(entity[1]));\n // The pod answers a miss with an EMPTY 404 body (rest/entities.ts `c.body(null, 404)`); so does a row the grant cannot read.\n return found && readableEntity(found, spaces) ? json(200, entityWire(found)) : new Response(null, { status: 404 });\n }\n const roles = /^\\/entities\\/([^/]+)\\/facets$/.exec(path);\n if (roles) {\n const found = entities.find((e) => e.id === decodeURIComponent(roles[1]));\n if (!found || !readableEntity(found, spaces)) return new Response(null, { status: 404 });\n // getEffectiveFacets under the whole floor: each live facet row, its role-profile, that profile's effective properties.\n return json(200, {\n facets: facetsOf(found, spaces).map((f) => ({\n facet: {\n id: f.facetId,\n entityId: found.id,\n profileId: `profile_${f.slug}`,\n userId: found.userId ?? user.id,\n // A stamped facet answers its space; a shared role's facet is stored pod-wide.\n workspaceId: f.sharedRole ? null : f.workspaceId,\n contextEntityId: null,\n status: f.status ?? null,\n statusCategory: null,\n properties: f.properties ?? {},\n metadata: {},\n createdByKind: null,\n createdByUserId: null,\n agentUserId: null,\n sourceProposalId: null,\n correlationId: null,\n createdAt: seededAt,\n updatedAt: seededAt,\n deletedAt: null,\n },\n profile: { id: `profile_${f.slug}`, slug: f.slug, profileKind: \"role\" },\n effectiveProperties: [],\n })),\n });\n }\n const doc = /^\\/documents\\/([^/]+)$/.exec(path);\n if (doc) {\n const format = query.get(\"format\") ?? \"raw\";\n if (format !== \"raw\" && format !== \"readable\") return json(400, { error: \"format must be raw or readable\" });\n const d = documents.find((x) => x.id === decodeURIComponent(doc[1]));\n if (!d) return json(404, { error: \"Document not found\" });\n // projectAgentDocument; the mock has no embeds, so `readable` = `raw`, and no sections are parsed.\n return json(200, {\n document: {\n id: d.id,\n title: d.title,\n type: d.type ?? \"markdown\",\n language: d.language ?? null,\n workspaceId: d.workspaceId ?? null,\n format,\n content: d.content,\n revision: d.revision ?? 1,\n version: d.version ?? 1,\n sections: [],\n diagnostics: [],\n updatedAt: d.updatedAt ?? seededAt,\n createdAt: d.createdAt ?? seededAt,\n },\n });\n }\n if (path === \"/focus-sessions\") {\n const ws = query.get(\"workspaceId\");\n const project = query.get(\"projectId\");\n if (!ws && !project) return json(400, { error: \"workspaceId or projectId is required\" });\n const status = query.get(\"status\") ?? \"all\";\n const lens = query.get(\"lens\") ?? \"all\";\n const kind = query.get(\"kind\") ?? \"all\";\n const subject = query.get(\"subjectEntityId\");\n const limit = Math.min(Math.max(Number(query.get(\"limit\") ?? 20) || 20, 1), 50);\n const rows = sessions\n .map(sessionRow)\n .filter((r) => (!ws || r.workspaceId === ws) && (!project || r.projectId === project))\n .filter((r) => status === \"all\" || r.status === status)\n .filter((r) => {\n const pending = (r.triage as { pending?: boolean } | undefined)?.pending === true;\n return lens === \"triage\" ? pending : lens === \"default\" ? !pending : true;\n })\n .filter((r) => kind === \"all\" || r.kind === kind)\n .filter((r) => !subject || r.subjectEntityId === subject)\n .sort((a, b) => String(b.startedAt).localeCompare(String(a.startedAt)));\n return json(200, rows.slice(0, limit));\n }\n return null;\n }\n\n function hub(method: string, path: string, query: URLSearchParams, headers: Record<string, string>, body: unknown): Response | \"reject\" {\n const failure = options.failures?.[path];\n if (failure === \"unreachable\") return \"reject\";\n const bearer = /^Bearer (.+)$/.exec(headers.authorization ?? \"\")?.[1];\n const row = bearer ? access.get(bearer) : undefined;\n if (!row || row.revoked || row.expiresAt <= now()) return json(401, { error: \"Unauthorized\" });\n switch (failure) {\n case \"rate_limited\":\n return json(429, { error: \"Too many requests\" }, { \"Retry-After\": \"30\" });\n case \"forbidden\":\n return json(403, { error: \"Forbidden\" });\n case \"door_unsupported\":\n return json(403, { error: \"This door is not available to a space-scoped key\", code: \"GRANT_DOOR_UNSUPPORTED\" });\n case \"step_up_required\":\n return json(403, { error: STEP_UP_MESSAGE });\n case \"email_unverified\":\n return json(409, { error: \"Add and verify an email on your Synap account to connect a pod.\", code: \"CP_ACCOUNT_EMAIL_REQUIRED\", recovery: { action: \"update_control_plane_profile\" } });\n case \"origin_insecure\":\n return json(409, { error: \"This application must be served over HTTPS to connect to a Pod.\", code: \"FEDERATED_APPLICATION_ORIGIN_INSECURE\" });\n case \"server\":\n return json(500, { error: \"Internal error\" });\n case \"unavailable\":\n return json(503, { error: \"Unavailable\" });\n }\n // The grant fence: aggregate reads are refused to a space-scoped token.\n if (path.startsWith(\"/knowledge/\") || path === \"/entities/retrieve\" || path === \"/memory/search\") {\n return json(403, { error: \"This door is not available to a space-scoped key\", code: \"GRANT_DOOR_UNSUPPORTED\" });\n }\n if (method === \"GET\" && path === \"/users/me\") return json(200, user);\n if (method === \"GET\" && path === \"/entities\") {\n // The pod answers an ARRAY (rest/entities.ts), not a page object.\n const ws = query.get(\"workspaceId\") || undefined;\n const kind = query.get(\"profileSlug\");\n const role = query.get(\"facetSlug\");\n // A workspace lens keeps the pod-wide rows unless told not to (rest/entities.ts: `!== \"false\"`).\n const podWide = query.get(\"includePodWide\") !== \"false\";\n const withFacets = query.get(\"includeFacets\") === \"true\";\n const offset = Number(query.get(\"offset\") ?? 0) || 0;\n const limit = Number(query.get(\"limit\") ?? 50) || 50;\n // Granted spaces' rows, plus the pod-wide rows roled in them (read-only, as a member of the space).\n const spaces = readSpaces(row.scope);\n const rows = entities.filter((e) => {\n if (!readableEntity(e, spaces, ws)) return false;\n // includePodWide=false keeps the rows with a role STAMPED in the space; it drops those reached only through a shared role.\n if (ws && !podWide && e.workspaceId !== ws && !facetsOf(e, spaces, ws).some((f) => !f.sharedRole)) return false;\n const slugs = facetsOf(e, spaces, ws).map((f) => f.slug);\n // A profileSlug naming a role matches its wearers too (entities.list's facet branch).\n return (!kind || e.profileSlug === kind || slugs.includes(kind)) && (!role || slugs.includes(role));\n });\n return json(\n 200,\n rows.slice(offset, offset + limit).map((e) => {\n const facets = withFacets ? facetsOf(e, spaces, ws).map(facetRow) : [];\n return facets.length > 0 ? { ...entityWire(e), facetSlugs: facets.map((f) => f.slug), facets } : entityWire(e);\n }),\n );\n }\n if (method === \"GET\" && path === \"/proposals\") {\n // The grant clause: proposals are read only where the token holds proposal.read (else none, not a 403).\n const readable = new Set(grant.filter((g) => g.permission === \"proposal.read\" && row.scope.includes(g.permission)).map((g) => g.workspaceId));\n const status = query.get(\"status\") ?? \"pending\";\n const ws = query.get(\"workspaceId\");\n const limit = Math.min(Math.max(Number(query.get(\"limit\") ?? 50) || 50, 1), 200);\n const offset = Number(query.get(\"offset\") ?? 0) || 0;\n // proposalIds: comma-separated and/or repeated; present but empty matches nothing.\n const idsRaw = query.getAll(\"proposalIds\");\n const ids = idsRaw.length > 0 ? new Set(idsRaw.flatMap((v) => v.split(\",\").map((x) => x.trim()).filter(Boolean))) : null;\n const rows = proposals\n .filter((p) => p.workspaceId !== null && readable.has(p.workspaceId))\n .filter((p) => (status === \"all\" || p.status === status) && (!ws || p.workspaceId === ws))\n .filter((p) => !ids || ids.has(p.id))\n .reverse(); // newest first\n const page = rows.slice(offset, offset + limit);\n return json(200, { proposals: page, limit, offset, total: rows.length, hasMore: offset + page.length < rows.length });\n }\n if (method === \"GET\") {\n const read = readSeeded(path, query, row.scope);\n if (read) return read;\n }\n const approve = method === \"POST\" ? /^\\/proposals\\/([^/]+)\\/approve$/.exec(path) : null;\n if (approve) {\n // rejectAgentReviewer: an agent credential never approves, before anything is read.\n if (actsAs !== \"person\") {\n return json(403, { error: \"An agent credential cannot approve proposals — approve is human review. Approve from a human session.\" });\n }\n if (!deviceFresh) return json(403, { error: STEP_UP_MESSAGE });\n const p = proposals.find((x) => x.id === decodeURIComponent(approve[1]));\n if (!p) return json(404, { error: \"Proposal not found\" });\n // Only where the person granted proposal.approve, for the proposal's own space.\n if (!grant.some((g) => g.permission === \"proposal.approve\" && row.scope.includes(g.permission) && g.workspaceId === p.workspaceId)) {\n return json(403, { error: \"You may not approve changes here\" });\n }\n if (p.status !== \"pending\") return json(409, { error: `The proposal is ${p.status}, not pending` });\n p.status = \"approved\";\n approvals.push(p.id);\n return json(200, { success: true, proposalId: p.id, proposal: { ...p } });\n }\n // Roles: an app cannot add one to an existing entity (no grantable `facet.attach`), nor change one on a pod-wide record (`permits()` refuses null).\n const attach = method === \"POST\" ? /^\\/entities\\/([^/]+)\\/facets$/.exec(path) : null;\n const facetPatch = method === \"PATCH\" ? /^\\/facets\\/([^/]+)$/.exec(path) : null;\n if (attach) return json(403, { error: \"grant does not allow\" });\n if (facetPatch) {\n const fid = decodeURIComponent(facetPatch[1]);\n const parent = entities.find((e) => rolesOf(e).some((f) => f.facetId === fid));\n if (parent && parent.workspaceId == null) return json(403, { error: \"grant does not allow\" });\n }\n // A pod-wide row's core fields are outside a space-scoped grant: refused, nothing written, no proposal.\n // The pod: 403 \"grant does not allow\" on the connected person's own record, 404 on a teammate's (outside the write floor).\n const patched = method === \"PATCH\" ? /^\\/entities\\/([^/]+)$/.exec(path) : null;\n if (patched) {\n const target = entities.find((e) => e.id === decodeURIComponent(patched[1]));\n if (target && target.workspaceId == null) {\n return typeof target.userId === \"string\" && target.userId !== user.id ? new Response(null, { status: 404 }) : json(403, { error: \"grant does not allow\" });\n }\n }\n if (method !== \"GET\") {\n writes.push({ method, path, body });\n const fields = body && typeof body === \"object\" ? (body as Record<string, unknown>) : {};\n const workspaceId = typeof fields.workspaceId === \"string\" ? fields.workspaceId : null;\n if (writeMode() === \"proposed\") {\n const proposalId = `prop_mock_${++proposalSeq}`;\n proposals.push({\n id: proposalId,\n proposalType: method === \"POST\" ? \"create\" : method === \"DELETE\" ? \"delete\" : \"update\",\n targetType: path.split(\"/\")[1]?.replace(/s$/, \"\") ?? \"entity\",\n targetId: null,\n status: \"pending\",\n workspaceId,\n createdAt: new Date(now()).toISOString(),\n correlationId: null,\n sessionId: null,\n agentUserId: MOCK_APP_AGENT_ID,\n ...(typeof fields.title === \"string\" ? { summary: `Create \"${fields.title}\"` } : {}),\n });\n return json(200, {\n status: \"proposed\",\n message: \"Sent for review\",\n proposalId,\n reviewUrl: `${issuer}/open/${proposalId}`,\n });\n }\n const id = `ent_mock_${writes.length}`;\n if (method === \"POST\" && path === \"/entities\") entities.push({ id, ...fields });\n return json(200, { status: \"created\", id });\n }\n return json(404, { error: \"Not found\" });\n }\n\n const mockFetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const request = typeof input === \"object\" && \"method\" in input ? input : null;\n const url = new URL(typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url);\n const method = (init?.method ?? request?.method ?? \"GET\").toUpperCase();\n const headers: Record<string, string> = {};\n new Headers(init?.headers ?? request?.headers).forEach((value, name) => {\n headers[name.toLowerCase()] = value;\n });\n const rawBody = typeof init?.body === \"string\" ? init.body : request ? await request.clone().text() : \"\";\n const isForm = (headers[\"content-type\"] ?? \"\").includes(\"application/x-www-form-urlencoded\");\n const form = isForm ? Object.fromEntries(new URLSearchParams(rawBody)) : null;\n requests.push({ method, url: url.href, headers, form });\n\n if (url.origin !== new URL(issuer).origin) throw new TypeError(`Failed to fetch: ${url.origin} is not the mock pod`);\n const path = url.pathname;\n if (method === \"GET\" && path === \"/.well-known/oauth-authorization-server\") return json(200, metadata());\n if (method === \"POST\" && path === \"/token\") return token(form ?? {});\n if (method === \"POST\" && path === \"/revoke\") {\n const t = form?.token ?? \"\";\n const r = refreshTokens.get(t);\n if (r && form?.client_id && form.client_id !== r.clientId) {\n return oauthError(\"unauthorized_client\", \"The token was not issued to this client\");\n }\n if (r) revokeFamily(r.family);\n const a = access.get(t);\n if (a) a.revoked = true;\n return new Response(null, { status: 200 });\n }\n const hubPath = /^\\/api\\/hub(\\/.*)$/.exec(path)?.[1];\n if (hubPath) {\n let body: unknown = undefined;\n try {\n body = rawBody ? JSON.parse(rawBody) : undefined;\n } catch {\n body = rawBody;\n }\n const res = hub(method, hubPath, url.searchParams, headers, body);\n if (res === \"reject\") throw new TypeError(\"Failed to fetch: mock pod unreachable\");\n return res;\n }\n return json(404, { error: \"Not found\" });\n };\n\n return {\n issuer,\n fetch: mockFetch as typeof fetch,\n requests,\n writes,\n proposals,\n approvals,\n settleProposal(id, status) {\n const p = proposals.find((x) => x.id === id);\n if (p) p.status = status;\n },\n async redeemElsewhere(t) {\n const row = refreshTokens.get(t);\n const res = await token({ grant_type: \"refresh_token\", refresh_token: t, client_id: row?.clientId ?? \"\" });\n if (res.status !== 200) throw new Error(`redeemElsewhere: the pod answered ${res.status}`);\n return (await res.json()) as { access_token: string; refresh_token: string; expires_in: number };\n },\n get graceAnswers() {\n return graceAnswers;\n },\n authorize(authorizeUrl, decision = {}) {\n const url = new URL(authorizeUrl);\n if (`${url.origin}${url.pathname}` !== `${issuer}/authorize`) throw new Error(`Not this pod's /authorize: ${authorizeUrl}`);\n const q = url.searchParams;\n const redirectUri = q.get(\"redirect_uri\");\n const clientId = q.get(\"client_id\");\n // Phase 1 (shown, never redirected): no verified redirect yet.\n if (!clientId || !redirectUri) throw new Error(\"Authorization request rejected: client_id and redirect_uri are required\");\n const answer = new URL(redirectUri);\n const state = decision.state ?? q.get(\"state\");\n const finish = (fields: Record<string, string>) => {\n for (const [k, v] of Object.entries(fields)) answer.searchParams.set(k, v);\n if (state !== null) answer.searchParams.set(\"state\", state);\n const iss = decision.iss === undefined ? issuer : decision.iss;\n if (iss !== null) answer.searchParams.set(\"iss\", iss);\n return answer.href;\n };\n if (q.get(\"response_type\") !== \"code\") return finish({ error: \"unsupported_response_type\" });\n if (q.get(\"code_challenge_method\") !== \"S256\" || !q.get(\"code_challenge\")) {\n return finish({ error: \"invalid_request\", error_description: \"PKCE S256 is required\" });\n }\n const resource = q.get(\"resource\");\n if (resource !== null && resource !== `${issuer}/api/hub` && resource !== `${issuer}/mcp`) {\n return finish({ error: \"invalid_target\" });\n }\n const scope = (q.get(\"scope\") ?? \"\").split(/\\s+/).filter(Boolean);\n if (scope.length === 0) return finish({ error: \"invalid_scope\" });\n if (decision.deny) return finish({ error: \"access_denied\" });\n const code = randomToken();\n codes.set(code, { clientId, redirectUri, challenge: q.get(\"code_challenge\")!, resource, scope, stepUp: actsAs === \"person\" && q.get(\"prompt\") === \"login\" });\n return finish({ code });\n },\n setActsAs(v) {\n actsAs = v ?? undefined;\n },\n expireStepUp() {\n deviceFresh = false;\n },\n consumeRefreshToken(t) {\n const row = refreshTokens.get(t);\n if (row) row.used = true;\n },\n loseNextRefreshRace() {\n loseNextRace = true;\n },\n get reuses() {\n return reuses;\n },\n revokeAll() {\n for (const row of access.values()) row.revoked = true;\n for (const row of refreshTokens.values()) row.revoked = true;\n },\n revokeAccessKeys() {\n for (const row of access.values()) row.revoked = true;\n },\n liveRefreshTokens() {\n return [...refreshTokens].filter(([, r]) => !r.used && !r.revoked).map(([t]) => t);\n },\n reset() {\n requests.length = 0;\n writes.length = 0;\n },\n };\n}\n","/**\n * The mock pod's data as ONE JSON-serialisable shape, so an app's mock mode,\n * smoke and screenshots replay a recorded snapshot (one file) instead of\n * fixtures built in app code:\n *\n * import { readFileSync } from \"node:fs\";\n * const seed = parseMockPodSeed(readFileSync(\"mock/pod-seed.json\", \"utf8\"));\n * const pod = createMockAuthServer({ seed });\n *\n * Rows are the pod's wire shapes (see `@synap-core/sdk/connect` hub-types):\n * `entities` as `GET /entities` answers them, `sessions` as `GET\n * /focus-sessions` rows (missing columns get the pod's defaults), `documents`\n * as `GET /documents/:id` (`sections` and `diagnostics` answered empty),\n * `relations` as graph edges for `GET /entities/:id/connections`, `proposals`\n * as `GET /proposals?view=basic` rows, `spaces` name each granted space's\n * template (`synap_grant[].templateSlug` on the token response).\n *\n * An entity's roles ride on its row as `facets`, the shape `GET /entities?\n * includeFacets=true` answers them (`{ facetId, slug, properties, status }`),\n * plus the seed-only space each is stamped in, so a seed row reads like a pod\n * row read with includeFacets. The mock derives `facetSlugs` and the reach rule\n * from them and serves neither field unless asked, as the pod.\n */\nimport type { MockProposal } from \"./auth-server\";\nimport { desugarSeedRoles } from \"./roles\";\n\n/** One role an entity wears (backend `FacetRowAnnotation`, plus the space it is stamped in). */\nexport interface MockSeedFacet {\n facetId: string;\n /** The role's slug, e.g. `lead`. */\n slug: string;\n /** The facet's overlay properties. Default `{}`. */\n properties?: Record<string, unknown>;\n /** Its lifecycle status. Default null. */\n status?: string | null;\n /**\n * Seed only, never served: the space the role is in, i.e. the space whose\n * members see the facet (stamped there, or a pod-wide facet of a role granted\n * to it). A role in a granted space puts a pod-wide entity in the app's\n * reach; a workspace lens sees the roles of that space only.\n */\n workspaceId: string;\n /**\n * Seed only, never served: the role is SHARED, i.e. stored pod-wide (null\n * `workspaceId`) and granted to `workspaceId`, which then means \"the space it\n * is granted to\". Default false = stamped in `workspaceId`. The pod treats the\n * two alike for reach, except `includePodWide=false` on a space lens, which\n * drops a pod-wide row reached only through a shared role.\n */\n sharedRole?: boolean;\n}\n\nexport interface MockSeedEntity {\n id: string;\n profileSlug?: string;\n workspaceId?: string | null;\n title?: string | null;\n properties?: Record<string, unknown>;\n /**\n * The roles (facets) it wears, in the wire shape plus the space each is in\n * (`MockSeedFacet`). SEED INPUT ONLY: the pod sends them only to\n * `includeFacets`, and so does the mock. A pod-wide entity (`workspaceId:\n * null`) with a role in a granted space is readable by the app, as a member\n * of that space sees it. Absent = none.\n */\n facets?: MockSeedFacet[];\n /**\n * @deprecated Use `facets`; removed in 2.0. Shorthand for `facets` entries\n * with no id and no overlay: `parseMockPodSeed` turns each into a facet (a\n * generated `facetId`, empty properties, a null status). A role stated in\n * both is refused.\n */\n seedRoles?: Array<{ profileSlug: string; workspaceId: string }>;\n [key: string]: unknown;\n}\n\nexport interface MockSeedSession {\n id: string;\n workspaceId?: string | null;\n projectId?: string | null;\n goal?: string;\n status?: string;\n /** Slots; `owner: \"human\"` ones are what waits on the person. */\n expectedOutputs?: Array<Record<string, unknown>>;\n /** The entity it is about: listed among that entity's connections. */\n subjectEntityId?: string | null;\n /** ISO 8601; the list is newest first by it. */\n startedAt?: string;\n [key: string]: unknown;\n}\n\nexport interface MockSeedDocument {\n id: string;\n title: string;\n content: string;\n type?: string;\n language?: string | null;\n workspaceId?: string | null;\n revision?: number;\n version?: number;\n createdAt?: string;\n updatedAt?: string;\n}\n\nexport interface MockSeedRelation {\n id: string;\n sourceEntityId: string;\n targetEntityId: string;\n type: string;\n createdAt?: string;\n}\n\nexport interface MockSeedSpace {\n id: string;\n name: string;\n /** The template it came from (e.g. `content-os`); absent = made by hand. */\n templateSlug?: string;\n}\n\nexport interface MockPodSeed {\n entities?: MockSeedEntity[];\n sessions?: MockSeedSession[];\n documents?: MockSeedDocument[];\n relations?: MockSeedRelation[];\n /** Missing fields default to a pending `create` of an `entity`, with null ids and the seed's load time. */\n proposals?: Array<Partial<MockProposal> & { id: string }>;\n spaces?: MockSeedSpace[];\n}\n\nconst KEYS = [\"entities\", \"sessions\", \"documents\", \"relations\", \"proposals\", \"spaces\"] as const;\n\n/** Required string fields per collection (the rest is free-form, as the pod's rows). */\nconst REQUIRED: Record<(typeof KEYS)[number], readonly string[]> = {\n entities: [\"id\"],\n sessions: [\"id\"],\n documents: [\"id\", \"title\", \"content\"],\n relations: [\"id\", \"sourceEntityId\", \"targetEntityId\", \"type\"],\n proposals: [\"id\"],\n spaces: [\"id\", \"name\"],\n};\n\n/**\n * Read a seed (JSON text or an already-parsed value) and check its shape:\n * every collection optional, each an array of objects carrying its required\n * string fields; unknown top-level keys are refused (a typo would otherwise\n * seed nothing). Throws `TypeError` naming the first bad path.\n */\nexport function parseMockPodSeed(input: string | unknown): MockPodSeed {\n const value: unknown = typeof input === \"string\" ? JSON.parse(input) : input;\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new TypeError(\"seed: expected an object\");\n const obj = value as Record<string, unknown>;\n for (const key of Object.keys(obj)) {\n if (!(KEYS as readonly string[]).includes(key)) throw new TypeError(`seed.${key}: unknown collection (expected ${KEYS.join(\", \")})`);\n }\n for (const key of KEYS) {\n const rows = obj[key];\n if (rows === undefined) continue;\n if (!Array.isArray(rows)) throw new TypeError(`seed.${key}: expected an array`);\n rows.forEach((row, i) => {\n if (!row || typeof row !== \"object\" || Array.isArray(row)) throw new TypeError(`seed.${key}[${i}]: expected an object`);\n for (const field of REQUIRED[key]) {\n if (typeof (row as Record<string, unknown>)[field] !== \"string\") throw new TypeError(`seed.${key}[${i}].${field}: expected a string`);\n }\n if (key === \"entities\") checkFacets((row as Record<string, unknown>).facets, `seed.entities[${i}].facets`);\n });\n }\n (obj.entities as Array<Record<string, unknown>> | undefined)?.forEach((row, i) => {\n const roles = row.seedRoles;\n if (roles === undefined) return;\n if (!Array.isArray(roles)) throw new TypeError(`seed.entities[${i}].seedRoles: expected an array`);\n roles.forEach((r, j) => {\n for (const field of [\"profileSlug\", \"workspaceId\"]) {\n if (!r || typeof r !== \"object\" || typeof (r as Record<string, unknown>)[field] !== \"string\") {\n throw new TypeError(`seed.entities[${i}].seedRoles[${j}].${field}: expected a string`);\n }\n }\n });\n });\n // A JSON round trip: what the mock serves is what a file could hold. Then ONE role model: seedRoles → facets.\n const out = JSON.parse(JSON.stringify(obj)) as MockPodSeed;\n if (out.entities) out.entities = out.entities.map((row, i) => desugarSeedRoles(row, `seed.entities[${i}]`) as MockSeedEntity);\n return out;\n}\n\nfunction checkFacets(facets: unknown, at: string): void {\n if (facets === undefined) return;\n if (!Array.isArray(facets)) throw new TypeError(`${at}: expected an array`);\n facets.forEach((f, j) => {\n if (!f || typeof f !== \"object\" || Array.isArray(f)) throw new TypeError(`${at}[${j}]: expected an object`);\n for (const field of [\"facetId\", \"slug\", \"workspaceId\"]) {\n if (typeof (f as Record<string, unknown>)[field] !== \"string\") throw new TypeError(`${at}[${j}].${field}: expected a string`);\n }\n const shared = (f as Record<string, unknown>).sharedRole;\n if (shared !== undefined && typeof shared !== \"boolean\") throw new TypeError(`${at}[${j}].sharedRole: expected a boolean`);\n });\n}\n","/**\n * A mock Synap Cloud pod chooser (Control Plane `GET /connect/pod`)\n * for \"Continue with Synap Cloud\" tests and a kit's mock mode. No network:\n * `choose()` stands in for the person signing in to the CP and picking a pod.\n *\n * Wire behaviour mirrors the CP route: it accepts only\n * `client_id` (an https CIMD URL; http on loopback only with\n * `allowInsecureLoopback`, for a kit's mock mode on http://localhost) and\n * `state` (`^[A-Za-z0-9._~-]{16,256}$`),\n * takes the return URL from the app's client metadata (`initiate_login_uri`),\n * never from the query, and answers `<initiate_login_uri>?iss=<pod issuer>&state=<state>`.\n * It never sees a code or a token.\n *\n * const cloud = createMockCloud();\n * createPodAppAuth({ ...config, cloudUrl: cloud.url });\n * cloud.choose(location, { pod: mockPod.issuer, metadata: auth.metadata }) → the app's return URL\n */\nimport { CLOUD_STATE_RE as STATE_RE, LOOPBACK_HOSTS } from \"../connect/rules\";\nimport type { ClientMetadataDocument } from \"../connect/types\";\n\n/** A placeholder Control Plane origin; never contacted. */\nexport const MOCK_CLOUD_URL = \"https://cp.mock-synap.test\";\n\n\nexport interface MockCloud {\n url: string;\n /** The chooser URLs the app sent browsers to. */\n requests: string[];\n /**\n * The person picks `pod` on the chooser: validates the request like the CP,\n * returns where the CP redirects the browser. Throws on a request the CP\n * refuses (shown as a page there, never redirected).\n */\n choose(location: string, opts: { pod: string; metadata: Pick<ClientMetadataDocument, \"client_id\" | \"initiate_login_uri\"> }): string;\n /** The person cancels on the chooser: `<initiate_login_uri>?state=…&error=access_denied`, no `iss`. */\n cancel(location: string, opts: { metadata: Pick<ClientMetadataDocument, \"client_id\" | \"initiate_login_uri\"> }): string;\n}\n\nexport function createMockCloud(options: { url?: string; allowInsecureLoopback?: boolean } = {}): MockCloud {\n const base = (options.url ?? MOCK_CLOUD_URL).replace(/\\/+$/, \"\");\n const requests: string[] = [];\n return {\n url: base,\n requests,\n choose(location, { pod, metadata }) {\n const back = check(location, metadata);\n back.searchParams.set(\"iss\", pod);\n back.searchParams.set(\"state\", new URL(location).searchParams.get(\"state\")!);\n return back.href;\n },\n cancel(location, { metadata }) {\n const back = check(location, metadata);\n back.searchParams.set(\"state\", new URL(location).searchParams.get(\"state\")!);\n back.searchParams.set(\"error\", \"access_denied\");\n return back.href;\n },\n };\n\n /** Validates like the CP (an HTML error there, never a redirect); returns the app's initiate_login_uri. */\n function check(location: string, metadata: Pick<ClientMetadataDocument, \"client_id\" | \"initiate_login_uri\">): URL {\n requests.push(location);\n const url = new URL(location);\n if (`${url.origin}${url.pathname}` !== `${base}/connect/pod`) throw new Error(`Not this CP's /connect/pod: ${location}`);\n const clientId = url.searchParams.get(\"client_id\");\n const state = url.searchParams.get(\"state\");\n if (!clientId || !cimdUrlAccepted(clientId)) throw new Error(\"Chooser refused: client_id must be an https CIMD URL\");\n if (!state || !STATE_RE.test(state)) throw new Error(\"Chooser refused: state is missing or malformed\");\n if (clientId !== metadata.client_id) throw new Error(\"Chooser refused: the client metadata is not this client_id's\");\n return new URL(metadata.initiate_login_uri);\n }\n\n /** https; http only on a loopback host, and only with `allowInsecureLoopback`. */\n function cimdUrlAccepted(clientId: string): boolean {\n let url: URL;\n try {\n url = new URL(clientId);\n } catch {\n return false;\n }\n if (url.protocol === \"https:\") return true;\n return url.protocol === \"http:\" && options.allowInsecureLoopback === true && LOOPBACK_HOSTS.has(url.hostname);\n }\n}\n","/**\n * @synap-core/sdk/testing — a mock pod: a fake `fetch` that answers the pod's\n * public doors (forms, shares, sites) from fixtures, with no network. Inject\n * it into the REAL client (`createPublicClient({ podUrl, fetch: pod.fetch })`)\n * so everything above the wire — status handling, typed errors, the models —\n * is the production path. For unit tests, a site's mock mode and a kit's\n * states gallery.\n *\n * Wire behaviour mirrors the backend doors: the uniform 404 for every miss,\n * the constant 202 on a submit, the site doors' query bounds (400), weak\n * ETags with If-None-Match → 304. Like a browser against the real doors, a\n * `credentials: \"include\"` request is refused (it rejects, as a CORS failure\n * does); with `{ browser: true }` a non-safelisted request header is too.\n *\n * tokens MOCK_TOKENS.form / .share / .htmlShare / .site the demo form, shares (markdown, html) and site\n * tokens MOCK_FAILURE_TOKENS.* one failure on every door\n * anything else the uniform 404\n *\n * Pod-app sign-in (`@synap-core/sdk/connect`): `createMockAuthServer()`, see\n * ./auth-server.ts, seeded from one JSON shape (`parseMockPodSeed`, ./seed.ts); Synap Cloud's pod chooser: `createMockCloud()`, ./cloud.ts.\n */\nimport type {\n PublicCollectionPage,\n PublicForm,\n PublicRecord,\n PublicRecordSummary,\n PublicShare,\n PublicSite,\n} from \"../public/client\";\nimport { MOCK_FORM, MOCK_HTML_SHARE, MOCK_SHARE, MOCK_SITE, type MockSite } from \"./fixtures\";\n\nexport { MOCK_FORM, MOCK_HTML_SHARE, MOCK_SHARE, MOCK_SITE };\nexport type { MockCollection, MockSite } from \"./fixtures\";\n// Pod-app sign-in: a mock authorization server + Hub REST doors.\nexport * from \"./auth-server\";\n// The mock pod's data as one JSON shape (1.5).\nexport * from \"./seed\";\n// Synap Cloud: a mock Control Plane pod chooser.\nexport * from \"./cloud\";\n\n/** A placeholder origin; never contacted. */\nexport const MOCK_POD_URL = \"https://mock.synap.invalid\";\n\nexport const MOCK_TOKENS = { form: \"demo-form\", share: \"demo\", htmlShare: \"demo-html\", site: \"demo-site\" } as const;\n\n/** The `Retry-After` the `rateLimitedRetryAfter` token sends. */\nexport const MOCK_RETRY_AFTER_SEC = 30;\n\n/** Tokens that make every door answer one failure, so each UI state can be rendered. */\nexport const MOCK_FAILURE_TOKENS = {\n /** 429 with no `Retry-After` (what the pod's public doors send today). */\n rateLimited: \"mock-rate-limited\",\n /** 429 with `Retry-After: 30`. */\n rateLimitedRetryAfter: \"mock-rate-limited-retry-after\",\n /** 403 `public_doors_disabled`: the owner switched public pages off. */\n doorsDisabled: \"mock-doors-disabled\",\n /** 500. */\n serverError: \"mock-server-error\",\n /** 503 (a read: `pod_unreachable` / `server`; a submit: `unavailable`). */\n unavailable: \"mock-unavailable\",\n /** No answer: the fetch rejects (`network` / `pod_unreachable`). */\n unreachable: \"mock-unreachable\",\n} as const;\n\nexport interface MockPodOptions {\n /** Forms by token (default: the demo form under `MOCK_TOKENS.form`). */\n forms?: Record<string, PublicForm>;\n /** Shares by token (default: the demo share under `MOCK_TOKENS.share`). */\n shares?: Record<string, PublicShare>;\n /** Sites by token (default: the demo site under `MOCK_TOKENS.site`). */\n sites?: Record<string, MockSite>;\n /** Refuse non-safelisted request headers, as a browser's CORS preflight would. */\n browser?: boolean;\n}\n\nexport interface MockRequest {\n method: string;\n url: string;\n /** Lower-cased header names. */\n headers: Record<string, string>;\n credentials: RequestCredentials | undefined;\n}\n\nexport interface MockSubmission {\n token: string;\n /** The parsed envelope (`fields`, `ticket`, `hp`, …). */\n body: unknown;\n /** The answer the mock gave. */\n status: 202 | 422;\n}\n\nexport interface MockPod {\n podUrl: string;\n fetch: typeof fetch;\n /** Every request seen, in order (assert credentials and headers on it). */\n requests: MockRequest[];\n /** Every submit seen, in order. */\n submissions: MockSubmission[];\n /** Forget `requests` and `submissions`. */\n reset(): void;\n}\n\nconst NOT_FOUND = { error: \"Not found\" };\nconst DOORS_DISABLED = {\n error: \"The owner has not turned on public pages and forms for this workspace.\",\n code: \"public_doors_disabled\",\n};\n/** Request headers a browser sends cross-origin without a preflight. */\nconst SAFELISTED = new Set([\"accept\", \"accept-language\", \"content-language\", \"content-type\"]);\n/** The only request header the real doors allow on a preflight. */\nconst PREFLIGHT_ALLOWED = new Set([\"content-type\"]);\n\nconst PUBLIC_ID_RE = /^p_[A-Za-z0-9]{16}$/;\nconst SLUG_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;\nconst SLUG_MAX_LENGTH = 96;\nconst DIGITS = /^\\d{1,9}$/;\nconst SORT_TERM = /^(-?)([A-Za-z][A-Za-z0-9_]{0,63})$/;\nconst MAX_OFFSET = 10_000;\nconst MAX_LIMIT = 100;\nconst MAX_SORT_KEYS = 3;\nconst PUBLISHED_AT = \"publishedAt\";\n\nfunction json(status: number, body: unknown, headers: Record<string, string> = {}): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-cache\", ...headers },\n });\n}\n\n/** FNV-1a, 32 bits: a stable weak validator, no crypto needed. */\nfunction weakEtag(value: unknown): string {\n let h = 0x811c9dc5;\n for (const ch of JSON.stringify(value)) {\n h ^= ch.charCodeAt(0);\n h = Math.imul(h, 0x01000193) >>> 0;\n }\n return `W/\"${h.toString(16).padStart(8, \"0\")}\"`;\n}\n\nfunction etagMatches(header: string | null, etag: string): boolean {\n if (!header) return false;\n if (header.trim() === \"*\") return true;\n const strip = (t: string) => t.trim().replace(/^W\\//, \"\");\n return header.split(\",\").some((t) => strip(t) === strip(etag));\n}\n\nfunction failure(token: string): Response | \"reject\" | null {\n switch (token) {\n case MOCK_FAILURE_TOKENS.rateLimited:\n return json(429, { error: \"Too many requests\", retryAfter: \"5 minutes\" });\n case MOCK_FAILURE_TOKENS.rateLimitedRetryAfter:\n return json(429, { error: \"Too many requests\" }, { \"Retry-After\": String(MOCK_RETRY_AFTER_SEC) });\n case MOCK_FAILURE_TOKENS.doorsDisabled:\n return json(403, DOORS_DISABLED);\n case MOCK_FAILURE_TOKENS.serverError:\n return json(500, { error: \"Internal error\" });\n case MOCK_FAILURE_TOKENS.unavailable:\n return json(503, { received: false });\n case MOCK_FAILURE_TOKENS.unreachable:\n return \"reject\";\n default:\n return null;\n }\n}\n\nfunction summary(record: PublicRecord): PublicRecordSummary {\n const { body: _body, ...rest } = record;\n return rest;\n}\n\nfunction manifest(site: MockSite): PublicSite {\n return {\n ...(site.title !== undefined ? { title: site.title } : {}),\n ...(site.description !== undefined ? { description: site.description } : {}),\n publishedOn: site.publishedOn,\n collections: Object.keys(site.collections)\n .sort()\n .map((key) => {\n const c = site.collections[key];\n return { key, count: c.records.length, sort: [...c.sort], pageSize: c.pageSize, addressing: c.addressing };\n }),\n };\n}\n\ntype Sort = Array<{ key: string; desc: boolean }>;\n\n/** The door's `parseCollectionQuery`: the same bounds, the same 400s. */\nfunction parseQuery(params: URLSearchParams, c: { sort: string[]; pageSize: number }): { offset: number; limit: number; sort: Sort } | string {\n for (const name of params.keys()) {\n if (name === \"embed\") return \"embed is not available\";\n if (name === \"ref\" || name.startsWith(\"ref[\")) return \"ref filter is not available\";\n }\n const one = (name: string): string | undefined | null => {\n const all = params.getAll(name);\n return all.length === 0 ? undefined : all.length === 1 ? all[0] : null;\n };\n const rawOffset = one(\"offset\");\n if (rawOffset === null || (rawOffset !== undefined && !DIGITS.test(rawOffset))) return \"invalid offset\";\n const offset = rawOffset === undefined ? 0 : Number(rawOffset);\n if (offset > MAX_OFFSET) return \"offset too large\";\n const rawLimit = one(\"limit\");\n if (rawLimit === null || (rawLimit !== undefined && !DIGITS.test(rawLimit))) return \"invalid limit\";\n const limit = Math.min(MAX_LIMIT, Math.max(1, rawLimit === undefined ? c.pageSize : Number(rawLimit)));\n const rawSort = one(\"sort\");\n if (rawSort === null) return \"invalid sort\";\n const terms =\n rawSort !== undefined ? rawSort.split(\",\") : c.sort.length > 0 ? [...c.sort] : [`-${PUBLISHED_AT}`];\n if (terms.length > MAX_SORT_KEYS) return \"invalid sort\";\n const allowed = new Set([PUBLISHED_AT, ...c.sort.map((s) => s.replace(/^-/, \"\"))]);\n const sort: Sort = [];\n for (const term of terms) {\n const m = SORT_TERM.exec(term);\n if (!m || !allowed.has(m[2]) || sort.some((s) => s.key === m[2])) return \"invalid sort\";\n sort.push({ key: m[2], desc: m[1] === \"-\" });\n }\n return { offset, limit, sort };\n}\n\n/** jsonb-like order within a type (strings < numbers < booleans); a missing value sorts last. */\nfunction compareRecords(sort: Sort) {\n const rank = (v: unknown) => (typeof v === \"string\" ? 0 : typeof v === \"number\" ? 1 : 2);\n const valueOf = (r: PublicRecord, key: string) => (key === PUBLISHED_AT ? r.publishedOn : r.properties[key]);\n return (a: PublicRecord, b: PublicRecord): number => {\n for (const { key, desc } of sort) {\n const va = valueOf(a, key);\n const vb = valueOf(b, key);\n if (va === undefined || vb === undefined) {\n if (va !== vb) return va === undefined ? 1 : -1;\n continue;\n }\n let d = rank(va) - rank(vb);\n if (d === 0) d = va < vb ? -1 : va > vb ? 1 : 0;\n if (d !== 0) return desc ? -d : d;\n }\n if (a.publishedOn !== b.publishedOn) return a.publishedOn < b.publishedOn ? 1 : -1;\n return a.publicId < b.publicId ? -1 : a.publicId > b.publicId ? 1 : 0;\n };\n}\n\n/** 200 with a weak ETag, or 304 when If-None-Match already holds it. */\nfunction cached(view: unknown, ifNoneMatch: string | null): Response {\n const etag = weakEtag(view);\n if (etagMatches(ifNoneMatch, etag)) {\n return new Response(null, { status: 304, headers: { ETag: etag, \"Cache-Control\": \"no-cache\" } });\n }\n return json(200, view, { ETag: etag });\n}\n\nfunction siteDoor(site: MockSite, rest: string[], params: URLSearchParams, ifNoneMatch: string | null): Response {\n if (rest.length === 0) return cached(manifest(site), ifNoneMatch);\n if (rest[0] !== \"collections\" || rest.length > 3 || !Object.hasOwn(site.collections, rest[1])) {\n return json(404, NOT_FOUND);\n }\n const c = site.collections[rest[1]];\n if (rest.length === 2) {\n const q = parseQuery(params, c);\n if (typeof q === \"string\") return json(400, { error: q });\n const sorted = [...c.records].sort(compareRecords(q.sort));\n const page: PublicCollectionPage = {\n items: sorted.slice(q.offset, q.offset + q.limit).map(summary),\n total: sorted.length,\n offset: q.offset,\n limit: q.limit,\n };\n return cached(page, ifNoneMatch);\n }\n const address = rest[2];\n const byPublicId = PUBLIC_ID_RE.test(address);\n if (!byPublicId && !(address.length <= SLUG_MAX_LENGTH && SLUG_RE.test(address))) return json(404, NOT_FOUND);\n const record = c.records.find((r) => (byPublicId ? r.publicId === address : r.slug === address));\n if (!record) return json(404, NOT_FOUND);\n if (params.has(\"embed\")) return json(400, { error: \"embed is not available\" });\n return cached(record, ifNoneMatch);\n}\n\n/** The door's 422 for answers that do not satisfy the form (required, enum). */\nfunction invalidKeys(form: PublicForm, body: unknown): string[] {\n const fields = (body as { fields?: unknown } | null)?.fields;\n if (typeof fields !== \"object\" || fields === null) return [];\n const answers = fields as Record<string, unknown>;\n return form.fields\n .filter((f) => {\n const v = answers[f.key];\n if (v === undefined || v === \"\" || v === null) return f.required === true;\n if (f.type === \"boolean\") return typeof v !== \"boolean\" || (f.required === true && v !== true);\n const allowed = f.constraints?.enum;\n return allowed !== undefined && !allowed.includes(String(v));\n })\n .map((f) => f.key);\n}\n\nexport function createMockPod(options: MockPodOptions = {}): MockPod {\n const forms = options.forms ?? { [MOCK_TOKENS.form]: MOCK_FORM };\n const shares = options.shares ?? { [MOCK_TOKENS.share]: MOCK_SHARE, [MOCK_TOKENS.htmlShare]: MOCK_HTML_SHARE };\n const sites = options.sites ?? { [MOCK_TOKENS.site]: MOCK_SITE };\n const requests: MockRequest[] = [];\n const submissions: MockSubmission[] = [];\n\n const mockFetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const request = typeof input === \"object\" && \"method\" in input ? input : null;\n const url = new URL(typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url);\n const method = (init?.method ?? request?.method ?? \"GET\").toUpperCase();\n const headers: Record<string, string> = {};\n new Headers(init?.headers ?? request?.headers).forEach((value, name) => {\n headers[name.toLowerCase()] = value;\n });\n const credentials = init?.credentials ?? request?.credentials;\n requests.push({ method, url: url.href, headers, credentials });\n\n // What a browser does against the real doors (`Access-Control-Allow-Origin: *`).\n if (credentials === \"include\") throw new TypeError(\"Failed to fetch: credentialed request to a public door\");\n if (options.browser) {\n const preflighted = Object.keys(headers).filter((h) => !SAFELISTED.has(h) && !PREFLIGHT_ALLOWED.has(h));\n if (preflighted.length > 0) throw new TypeError(`Failed to fetch: preflight refuses ${preflighted.join(\", \")}`);\n }\n\n const m = url.pathname.match(/^\\/api\\/hub\\/public\\/(forms|shares|sites)\\/(.+)$/);\n if (!m) return json(404, NOT_FOUND);\n let segments: string[];\n try {\n segments = m[2].split(\"/\").map(decodeURIComponent);\n } catch {\n return json(404, NOT_FOUND);\n }\n const [token, ...rest] = segments;\n const failed = failure(token);\n if (failed === \"reject\") throw new TypeError(\"Failed to fetch: mock pod unreachable\");\n if (failed) return failed;\n\n const door = m[1];\n if (door === \"forms\" && method === \"POST\" && rest.length === 0) {\n let body: unknown = null;\n try {\n body = JSON.parse(typeof init?.body === \"string\" ? init.body : \"null\");\n } catch {\n body = null;\n }\n const form = Object.hasOwn(forms, token) ? forms[token] : undefined;\n const invalid = form ? invalidKeys(form, body) : [];\n const status = invalid.length > 0 ? 422 : 202;\n submissions.push({ token, body, status });\n return status === 422 ? json(422, { received: false, invalid }) : json(202, { received: true });\n }\n if (method !== \"GET\") return json(404, NOT_FOUND);\n if (door === \"forms\" && rest.length === 0 && Object.hasOwn(forms, token)) return json(200, forms[token]);\n if (door === \"shares\" && rest.length === 0 && Object.hasOwn(shares, token)) return json(200, shares[token]);\n if (door === \"sites\" && Object.hasOwn(sites, token)) {\n return siteDoor(sites[token], rest, url.searchParams, headers[\"if-none-match\"] ?? null);\n }\n return json(404, NOT_FOUND);\n };\n\n return {\n podUrl: MOCK_POD_URL,\n fetch: mockFetch as typeof fetch,\n requests,\n submissions,\n reset() {\n requests.length = 0;\n submissions.length = 0;\n },\n };\n}\n"],"mappings":"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","names":["failure","json"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synap-core/sdk",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "description": "Type-safe tRPC client SDK for Synap data pods, public-door client, and server-only pod-app sign-in",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -55,11 +55,17 @@
55
55
  "dist",
56
56
  "src",
57
57
  "!src/__tests__",
58
- "CHANGELOG.md"
58
+ "CHANGELOG.md",
59
+ "AGENTS.md"
59
60
  ],
60
61
  "engines": {
61
62
  "node": ">=20"
62
63
  },
64
+ "scripts": {
65
+ "build": "tsup",
66
+ "typecheck": "tsc --noEmit",
67
+ "test": "vitest run"
68
+ },
63
69
  "keywords": [
64
70
  "synap",
65
71
  "sdk",
@@ -91,10 +97,5 @@
91
97
  "url": "git+https://github.com/Synap-core/app-bases.git",
92
98
  "directory": "packages/sdk"
93
99
  },
94
- "license": "MIT",
95
- "scripts": {
96
- "build": "tsup",
97
- "typecheck": "tsc --noEmit",
98
- "test": "vitest run"
99
- }
100
- }
100
+ "license": "MIT"
101
+ }