@asturiu/v0-sdk 0.0.0-stage → 1.0.0

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.
Files changed (239) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +5 -0
  4. package/README.md +82 -2
  5. package/contract/assertion-vectors.json +90 -0
  6. package/contract/schemas/branding.schema.json +46 -0
  7. package/contract/schemas/definitions.schema.json +376 -0
  8. package/contract/schemas/portal.schema.json +56 -0
  9. package/contract/tenant-api-routes.json +165 -0
  10. package/dist/branding.d.ts +131 -0
  11. package/dist/branding.d.ts.map +1 -0
  12. package/dist/branding.js +206 -0
  13. package/dist/branding.js.map +1 -0
  14. package/dist/changesets.d.ts +58 -0
  15. package/dist/changesets.d.ts.map +1 -0
  16. package/dist/changesets.js +18 -0
  17. package/dist/changesets.js.map +1 -0
  18. package/dist/cli/bin.d.ts +3 -0
  19. package/dist/cli/bin.d.ts.map +1 -0
  20. package/dist/cli/bin.js +12 -0
  21. package/dist/cli/bin.js.map +1 -0
  22. package/dist/cli/changesets.d.ts +14 -0
  23. package/dist/cli/changesets.d.ts.map +1 -0
  24. package/dist/cli/changesets.js +252 -0
  25. package/dist/cli/changesets.js.map +1 -0
  26. package/dist/cli/cli.d.ts +37 -0
  27. package/dist/cli/cli.d.ts.map +1 -0
  28. package/dist/cli/cli.js +415 -0
  29. package/dist/cli/cli.js.map +1 -0
  30. package/dist/cli/context.d.ts +147 -0
  31. package/dist/cli/context.d.ts.map +1 -0
  32. package/dist/cli/context.js +258 -0
  33. package/dist/cli/context.js.map +1 -0
  34. package/dist/cli/engine.d.ts +59 -0
  35. package/dist/cli/engine.d.ts.map +1 -0
  36. package/dist/cli/engine.js +85 -0
  37. package/dist/cli/engine.js.map +1 -0
  38. package/dist/cli/feedback.d.ts +40 -0
  39. package/dist/cli/feedback.d.ts.map +1 -0
  40. package/dist/cli/feedback.js +420 -0
  41. package/dist/cli/feedback.js.map +1 -0
  42. package/dist/cli/files.d.ts +83 -0
  43. package/dist/cli/files.d.ts.map +1 -0
  44. package/dist/cli/files.js +389 -0
  45. package/dist/cli/files.js.map +1 -0
  46. package/dist/cli/index.d.ts +8 -0
  47. package/dist/cli/index.d.ts.map +1 -0
  48. package/dist/cli/index.js +8 -0
  49. package/dist/cli/index.js.map +1 -0
  50. package/dist/cli/overview.d.ts +6 -0
  51. package/dist/cli/overview.d.ts.map +1 -0
  52. package/dist/cli/overview.js +379 -0
  53. package/dist/cli/overview.js.map +1 -0
  54. package/dist/cli/parts.d.ts +5 -0
  55. package/dist/cli/parts.d.ts.map +1 -0
  56. package/dist/cli/parts.js +414 -0
  57. package/dist/cli/parts.js.map +1 -0
  58. package/dist/cli/sources.d.ts +37 -0
  59. package/dist/cli/sources.d.ts.map +1 -0
  60. package/dist/cli/sources.js +91 -0
  61. package/dist/cli/sources.js.map +1 -0
  62. package/dist/cli/terminal.d.ts +135 -0
  63. package/dist/cli/terminal.d.ts.map +1 -0
  64. package/dist/cli/terminal.js +353 -0
  65. package/dist/cli/terminal.js.map +1 -0
  66. package/dist/cli/ui-page.d.ts +8 -0
  67. package/dist/cli/ui-page.d.ts.map +1 -0
  68. package/dist/cli/ui-page.js +216 -0
  69. package/dist/cli/ui-page.js.map +1 -0
  70. package/dist/cli/ui.d.ts +54 -0
  71. package/dist/cli/ui.d.ts.map +1 -0
  72. package/dist/cli/ui.js +251 -0
  73. package/dist/cli/ui.js.map +1 -0
  74. package/dist/client.d.ts +88 -0
  75. package/dist/client.d.ts.map +1 -0
  76. package/dist/client.js +165 -0
  77. package/dist/client.js.map +1 -0
  78. package/dist/contacts.d.ts +43 -0
  79. package/dist/contacts.d.ts.map +1 -0
  80. package/dist/contacts.js +46 -0
  81. package/dist/contacts.js.map +1 -0
  82. package/dist/definition-set.d.ts +731 -0
  83. package/dist/definition-set.d.ts.map +1 -0
  84. package/dist/definition-set.js +659 -0
  85. package/dist/definition-set.js.map +1 -0
  86. package/dist/definitions.d.ts +42 -0
  87. package/dist/definitions.d.ts.map +1 -0
  88. package/dist/definitions.js +154 -0
  89. package/dist/definitions.js.map +1 -0
  90. package/dist/enrolment.d.ts +9 -0
  91. package/dist/enrolment.d.ts.map +1 -0
  92. package/dist/enrolment.js +8 -0
  93. package/dist/enrolment.js.map +1 -0
  94. package/dist/fill.d.ts +73 -0
  95. package/dist/fill.d.ts.map +1 -0
  96. package/dist/fill.js +46 -0
  97. package/dist/fill.js.map +1 -0
  98. package/dist/index.d.ts +39 -0
  99. package/dist/index.d.ts.map +1 -0
  100. package/dist/index.js +39 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/notifications.d.ts +33 -0
  103. package/dist/notifications.d.ts.map +1 -0
  104. package/dist/notifications.js +36 -0
  105. package/dist/notifications.js.map +1 -0
  106. package/dist/oidc.d.ts +122 -0
  107. package/dist/oidc.d.ts.map +1 -0
  108. package/dist/oidc.js +150 -0
  109. package/dist/oidc.js.map +1 -0
  110. package/dist/overlay.d.ts +109 -0
  111. package/dist/overlay.d.ts.map +1 -0
  112. package/dist/overlay.js +58 -0
  113. package/dist/overlay.js.map +1 -0
  114. package/dist/passes.d.ts +95 -0
  115. package/dist/passes.d.ts.map +1 -0
  116. package/dist/passes.js +140 -0
  117. package/dist/passes.js.map +1 -0
  118. package/dist/portal-options.d.ts +65 -0
  119. package/dist/portal-options.d.ts.map +1 -0
  120. package/dist/portal-options.js +120 -0
  121. package/dist/portal-options.js.map +1 -0
  122. package/dist/reads.d.ts +41 -0
  123. package/dist/reads.d.ts.map +1 -0
  124. package/dist/reads.js +44 -0
  125. package/dist/reads.js.map +1 -0
  126. package/dist/recovery-words.d.ts +8 -0
  127. package/dist/recovery-words.d.ts.map +1 -0
  128. package/dist/recovery-words.js +136 -0
  129. package/dist/recovery-words.js.map +1 -0
  130. package/dist/recovery.d.ts +198 -0
  131. package/dist/recovery.d.ts.map +1 -0
  132. package/dist/recovery.js +112 -0
  133. package/dist/recovery.js.map +1 -0
  134. package/dist/reveal.d.ts +35 -0
  135. package/dist/reveal.d.ts.map +1 -0
  136. package/dist/reveal.js +66 -0
  137. package/dist/reveal.js.map +1 -0
  138. package/dist/seal.d.ts +15 -0
  139. package/dist/seal.d.ts.map +1 -0
  140. package/dist/seal.js +0 -0
  141. package/dist/seal.js.map +1 -0
  142. package/dist/session.d.ts +66 -0
  143. package/dist/session.d.ts.map +1 -0
  144. package/dist/session.js +61 -0
  145. package/dist/session.js.map +1 -0
  146. package/dist/signing-in-mark.d.ts +14 -0
  147. package/dist/signing-in-mark.d.ts.map +1 -0
  148. package/dist/signing-in-mark.js +24 -0
  149. package/dist/signing-in-mark.js.map +1 -0
  150. package/dist/signing-in.d.ts +22 -0
  151. package/dist/signing-in.d.ts.map +1 -0
  152. package/dist/signing-in.js +203 -0
  153. package/dist/signing-in.js.map +1 -0
  154. package/dist/tags.d.ts +96 -0
  155. package/dist/tags.d.ts.map +1 -0
  156. package/dist/tags.js +88 -0
  157. package/dist/tags.js.map +1 -0
  158. package/dist/tenant-subscription.d.ts +47 -0
  159. package/dist/tenant-subscription.d.ts.map +1 -0
  160. package/dist/tenant-subscription.js +7 -0
  161. package/dist/tenant-subscription.js.map +1 -0
  162. package/dist/testing/index.d.ts +125 -0
  163. package/dist/testing/index.d.ts.map +1 -0
  164. package/dist/testing/index.js +320 -0
  165. package/dist/testing/index.js.map +1 -0
  166. package/dist/theme.d.ts +237 -0
  167. package/dist/theme.d.ts.map +1 -0
  168. package/dist/theme.js +504 -0
  169. package/dist/theme.js.map +1 -0
  170. package/dist/tickets.d.ts +152 -0
  171. package/dist/tickets.d.ts.map +1 -0
  172. package/dist/tickets.js +65 -0
  173. package/dist/tickets.js.map +1 -0
  174. package/dist/tiers.d.ts +168 -0
  175. package/dist/tiers.d.ts.map +1 -0
  176. package/dist/tiers.js +341 -0
  177. package/dist/tiers.js.map +1 -0
  178. package/dist/types.d.ts +885 -0
  179. package/dist/types.d.ts.map +1 -0
  180. package/dist/types.js +12 -0
  181. package/dist/types.js.map +1 -0
  182. package/dist/urlid.d.ts +50 -0
  183. package/dist/urlid.d.ts.map +1 -0
  184. package/dist/urlid.js +78 -0
  185. package/dist/urlid.js.map +1 -0
  186. package/dist/version.d.ts +15 -0
  187. package/dist/version.d.ts.map +1 -0
  188. package/dist/version.js +15 -0
  189. package/dist/version.js.map +1 -0
  190. package/make/asturiu.mk +43 -0
  191. package/package.json +63 -4
  192. package/src/branding.ts +221 -0
  193. package/src/changesets.ts +61 -0
  194. package/src/cli/bin.ts +12 -0
  195. package/src/cli/changesets.ts +233 -0
  196. package/src/cli/cli.ts +425 -0
  197. package/src/cli/context.ts +299 -0
  198. package/src/cli/engine.ts +112 -0
  199. package/src/cli/feedback.ts +406 -0
  200. package/src/cli/files.ts +371 -0
  201. package/src/cli/index.ts +7 -0
  202. package/src/cli/overview.ts +343 -0
  203. package/src/cli/parts.ts +371 -0
  204. package/src/cli/sources.ts +111 -0
  205. package/src/cli/terminal.ts +384 -0
  206. package/src/cli/ui-page.ts +215 -0
  207. package/src/cli/ui.ts +266 -0
  208. package/src/client.ts +202 -0
  209. package/src/contacts.ts +61 -0
  210. package/src/definition-set.ts +965 -0
  211. package/src/definitions.ts +156 -0
  212. package/src/enrolment.ts +10 -0
  213. package/src/fill.ts +83 -0
  214. package/src/index.ts +38 -0
  215. package/src/notifications.ts +55 -0
  216. package/src/oidc.ts +199 -0
  217. package/src/overlay.ts +137 -0
  218. package/src/passes.ts +168 -0
  219. package/src/portal-options.ts +125 -0
  220. package/src/reads.ts +71 -0
  221. package/src/recovery-words.ts +137 -0
  222. package/src/recovery.ts +269 -0
  223. package/src/reveal.ts +72 -0
  224. package/src/seal.ts +0 -0
  225. package/src/session.ts +93 -0
  226. package/src/signing-in-mark.ts +23 -0
  227. package/src/signing-in.ts +213 -0
  228. package/src/tags.ts +146 -0
  229. package/src/tenant-subscription.ts +44 -0
  230. package/src/testing/index.ts +337 -0
  231. package/src/theme.ts +628 -0
  232. package/src/tickets.ts +195 -0
  233. package/src/tiers.ts +397 -0
  234. package/src/types.ts +847 -0
  235. package/src/urlid.ts +77 -0
  236. package/src/version.ts +15 -0
  237. package/templates/asturiu/branding.json +4 -0
  238. package/templates/asturiu/definitions.json +23 -0
  239. package/templates/asturiu/portal.json +16 -0
@@ -0,0 +1,125 @@
1
+ import type { RepositoryBranding, TenantSource } from "../branding.js";
2
+ import type { ChangesetStatus, FeedbackReport, TenantChangeset } from "../changesets.js";
3
+ import { type DefinitionStatus, type DefinitionSubmitResult, type EngineInfo, type TenantKeyRecord, type TenantKeyScope } from "../definition-set.js";
4
+ import type { PortalPage } from "../portal-options.js";
5
+ import type { TagView } from "../tags.js";
6
+ import type { AnnouncementItem, TicketView } from "../tickets.js";
7
+ export type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
8
+ export interface StandInOptions {
9
+ /** The Tenant key whose assertions it takes; without one, any well-formed assertion passes. */
10
+ key?: string;
11
+ /** What the key reaches (default: every scope). */
12
+ scopes?: TenantKeyScope[];
13
+ /** Routes it answers with 404, as an older Engine does: `"GET /tenant/v0/key"`. */
14
+ missing?: string[];
15
+ /** Answer every call with this status (`401`: the key was refused). */
16
+ refuse?: number;
17
+ /** Throw as `fetch` does when nothing answers (`ECONNREFUSED`), or another network code. */
18
+ down?: boolean | string;
19
+ engine?: Partial<EngineInfo>;
20
+ definitions?: Partial<DefinitionStatus> & {
21
+ /** How it answers a submitted set other than the live one: applied at once (default) or waiting for approval. */
22
+ submit?: "apply" | "wait" | ((set: Record<string, unknown>, hash: string) => DefinitionSubmitResult);
23
+ };
24
+ branding?: {
25
+ source?: TenantSource;
26
+ branding?: RepositoryBranding;
27
+ };
28
+ portal?: {
29
+ source?: TenantSource;
30
+ portal?: Record<string, unknown>;
31
+ redirected?: PortalPage[];
32
+ };
33
+ changesets?: TenantChangeset[];
34
+ /** Documents of the Engine site, by their whole address: what `changesets pull` fetches. */
35
+ documents?: Record<string, string>;
36
+ feedback?: TicketView[];
37
+ tickets?: TicketView[];
38
+ announcements?: {
39
+ items?: TicketView[];
40
+ platform?: AnnouncementItem[];
41
+ };
42
+ tags?: TagView[];
43
+ keyRecord?: Partial<TenantKeyRecord>;
44
+ now?: () => number;
45
+ }
46
+ export interface StandInCall {
47
+ method: string;
48
+ path: string;
49
+ query: string;
50
+ body: unknown;
51
+ status: number;
52
+ /** The SDK version the caller named in its User-Agent, as the Tenant API forwards it. */
53
+ sdk_version: string | null;
54
+ }
55
+ /** A Tenant key for tests: made here, registered with no Engine, so a real Tenant API refuses it. */
56
+ export declare function testTenantKey(slug?: string, kid?: string): Promise<string>;
57
+ /** The in-memory Tenant API. `fetch` is what the SDK's calls and `asturiu-v0-tenant` take as their `fetch`. */
58
+ export declare function createTenantApiStandIn(o?: StandInOptions): {
59
+ fetch: FetchLike;
60
+ handle: (request: Request) => Promise<Response>;
61
+ state: {
62
+ engine: EngineInfo;
63
+ definitions: DefinitionStatus;
64
+ branding: {
65
+ source: "admin_ui" | "repository";
66
+ branding: RepositoryBranding;
67
+ };
68
+ portal: {
69
+ source: "admin_ui" | "repository";
70
+ portal: Record<string, unknown>;
71
+ redirected: ("profile" | "security" | "plan" | "privacy" | "recovery" | "support")[];
72
+ };
73
+ changesets: {
74
+ url: string | null;
75
+ ticket: string | null;
76
+ status: ChangesetStatus | null;
77
+ number: number;
78
+ slug: string;
79
+ file: string;
80
+ date: string;
81
+ title: string;
82
+ applies_to: string;
83
+ decisions: string[];
84
+ action_required: boolean;
85
+ deadline: string | null;
86
+ sdk_version: string | null;
87
+ }[];
88
+ feedback: TicketView[];
89
+ tickets: TicketView[];
90
+ announcements: TicketView[];
91
+ platform: AnnouncementItem[];
92
+ tags: {
93
+ id: string;
94
+ name: string;
95
+ shown: string;
96
+ scope: "platform" | "tenant";
97
+ tenant?: string;
98
+ subject: import("../tags.js").TagSubject;
99
+ visibility: import("../tags.js").TagVisibility;
100
+ description: string;
101
+ colour: import("../tags.js").TagColour;
102
+ rules: import("../tags.js").TagRule[];
103
+ effects: import("../tags.js").TagEffect[];
104
+ system: boolean;
105
+ subjects: number;
106
+ created_at: string;
107
+ updated_at: string;
108
+ }[];
109
+ customerTags: Map<string, Set<string>>;
110
+ tiers: {
111
+ source: TenantSource;
112
+ tiers: {};
113
+ default_tier: string | null;
114
+ };
115
+ reports: FeedbackReport[];
116
+ };
117
+ calls: StandInCall[];
118
+ routes: readonly {
119
+ method: string;
120
+ path: string;
121
+ scope: TenantKeyScope | null;
122
+ }[];
123
+ };
124
+ export type TenantApiStandIn = ReturnType<typeof createTenantApiStandIn>;
125
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,320 @@
1
+ /**
2
+ * `@asturiu/v0-sdk/testing` (ADR-074 §5): an in-memory stand-in for the Tenant API, so a Tenant's CI can run its
3
+ * start-up code and `asturiu-v0-tenant` without a key the Engine knows, a network or an Engine. Node only.
4
+ *
5
+ * It answers every route of `TENANT_API_ROUTES` the way the Tenant API does: a signed assertion on every call (checked
6
+ * against the stand-in's key when one is given), a `404` for a route the key's scopes do not reach, problem documents
7
+ * for refusals. It holds its state in memory and records each call. It is a stand-in, not the Engine: it plans no
8
+ * Definition change and checks no Definition rule.
9
+ */
10
+ import { createHash, createPrivateKey, createPublicKey, verify } from "node:crypto";
11
+ import { TENANT_API_ROUTES, TENANT_ASSERTION_AUDIENCE, TENANT_ASSERTION_MAX_SECONDS, TENANT_KEY_SCOPES, definitionSetHash, formatTenantKey, fromB64url, generateTenantKeyPair, keyReachesRoute, matchTenantApiRoute, parseTenantKey } from "../definition-set.js";
12
+ import { SDK_VERSION } from "../version.js";
13
+ const ALL_PAGES = ["profile", "security", "plan", "privacy", "recovery", "support"];
14
+ const ALL_SWITCHES = ["account_link", "open_app", "back_link", "language_menu", "appearance"];
15
+ /** A Tenant key for tests: made here, registered with no Engine, so a real Tenant API refuses it. */
16
+ export async function testTenantKey(slug = "acme", kid = "0123456789abcdef") {
17
+ return formatTenantKey({ slug, kid, pkcs8: (await generateTenantKeyPair()).privatePkcs8 });
18
+ }
19
+ const problem = (status, type, detail) => new Response(JSON.stringify({ type, title: type.replace(/-/g, " "), status, detail }), { status, headers: { "content-type": "application/problem+json" } });
20
+ const ok = (body, status = 200, headers = {}) => new Response(body === undefined ? null : JSON.stringify(body), { status, headers: { "content-type": "application/json", ...headers } });
21
+ const b64 = (s) => JSON.parse(Buffer.from(s, "base64url").toString("utf8"));
22
+ function post(at, body, mine, label) {
23
+ return { id: `pst-${createHash("sha256").update(at + body).digest("hex").slice(0, 12)}`, at, side: mine ? "requester" : "handling", visibility: "all", author: { label, mine }, body, refs: [] };
24
+ }
25
+ function ticket(o) {
26
+ return {
27
+ arid: o.arid,
28
+ scope: "tenant",
29
+ direction: o.direction ?? "tenant_platform",
30
+ primary: o.primary ?? "request",
31
+ secondary: null,
32
+ type_label: o.primary === "announcement" ? "Announcement" : "Request",
33
+ subject: o.subject,
34
+ status: o.status ?? "new",
35
+ priority: "normal",
36
+ archived: false,
37
+ created_at: o.at,
38
+ updated_at: o.at,
39
+ side: "requester",
40
+ unread: false,
41
+ with_label: o.with_label ?? "Asturiu",
42
+ parties: [],
43
+ posts: o.body ? [post(o.at, o.body, true, "Your servers")] : [],
44
+ links: [],
45
+ refs: [],
46
+ audience: null,
47
+ hold_until: null,
48
+ closed_at: null,
49
+ can: { post: true, note: false, triage: false, statuses: ["canceled", "resolved"], reopen: false },
50
+ };
51
+ }
52
+ /** The in-memory Tenant API. `fetch` is what the SDK's calls and `asturiu-v0-tenant` take as their `fetch`. */
53
+ export function createTenantApiStandIn(o = {}) {
54
+ const now = o.now ?? (() => Date.now());
55
+ const iso = () => new Date(now()).toISOString();
56
+ const scopes = o.scopes ?? [...TENANT_KEY_SCOPES];
57
+ let counter = 0;
58
+ const id = (type) => `ARID:0:global:${type}:01STANDIN${String(++counter).padStart(17, "0")}`;
59
+ const seenJti = new Set();
60
+ const publicKey = o.key ? createPublicKey(createPrivateKey({ key: Buffer.from(fromB64url(parseTenantKey(o.key).pkcs8)), format: "der", type: "pkcs8" })) : null;
61
+ const state = {
62
+ engine: { version: "0.1.0", released_at: "2026-11-09", latest_changeset: 0, site: { docs: "https://engine.example/docs/tenants", changesets: "https://engine.example/changesets" }, sdk: { built_with: SDK_VERSION, minimum: SDK_VERSION }, ...o.engine },
63
+ definitions: { revision: 1, hash: null, source: "repository", auto_apply: "safe", waiting: [], ...o.definitions },
64
+ branding: { source: o.branding?.source ?? "repository", branding: o.branding?.branding ?? {} },
65
+ portal: { source: o.portal?.source ?? "repository", portal: { ...Object.fromEntries(ALL_SWITCHES.map((s) => [s, true])), pages: Object.fromEntries(ALL_PAGES.map((p) => [p, { mode: "portal" }])), ...o.portal?.portal }, redirected: o.portal?.redirected ?? [] },
66
+ changesets: (o.changesets ?? []).map((c) => ({ ...c })),
67
+ feedback: (o.feedback ?? []).map((t) => structuredClone(t)),
68
+ tickets: (o.tickets ?? []).map((t) => structuredClone(t)),
69
+ announcements: (o.announcements?.items ?? []).map((t) => structuredClone(t)),
70
+ platform: o.announcements?.platform ?? [],
71
+ tags: (o.tags ?? []).map((t) => ({ ...t })),
72
+ customerTags: new Map(),
73
+ tiers: { source: "repository", tiers: {}, default_tier: null },
74
+ reports: [],
75
+ };
76
+ const calls = [];
77
+ const submit = o.definitions?.submit ?? "apply";
78
+ /** The assertion, as the Tenant API and the Operations API check it; null when it passes. */
79
+ function refuseAssertion(headers, method, path, body) {
80
+ const m = /^Asturiu-Assertion ([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)$/.exec(headers.get("authorization") ?? "");
81
+ if (!m)
82
+ return problem(401, "unauthorized", "a signed assertion is required");
83
+ let header;
84
+ let claims;
85
+ try {
86
+ header = b64(m[1]);
87
+ claims = b64(m[2]);
88
+ }
89
+ catch {
90
+ return problem(401, "unauthorized", "a signed assertion is required");
91
+ }
92
+ if (header.alg !== "EdDSA" || typeof header.kid !== "string")
93
+ return problem(401, "unauthorized", "invalid assertion");
94
+ if (o.key) {
95
+ const k = parseTenantKey(o.key);
96
+ // An unknown key or Tenant is nothing to the Engine: 404, as the Operations API answers.
97
+ if (header.kid !== k.kid || claims.iss !== k.slug)
98
+ return problem(404, "not-found", "Not Found");
99
+ if (!verify(null, Buffer.from(`${m[1]}.${m[2]}`), publicKey, Buffer.from(m[3], "base64url")))
100
+ return problem(401, "unauthorized", "invalid signature");
101
+ }
102
+ const t = Math.floor(now() / 1000);
103
+ if (claims.aud !== TENANT_ASSERTION_AUDIENCE)
104
+ return problem(401, "unauthorized", "wrong audience");
105
+ if (claims.htm !== method || claims.htu !== path)
106
+ return problem(401, "unauthorized", "the assertion names another request");
107
+ if (typeof claims.exp !== "number" || typeof claims.iat !== "number" || claims.exp < t || claims.exp - claims.iat > TENANT_ASSERTION_MAX_SECONDS)
108
+ return problem(401, "unauthorized", "assertion expired");
109
+ if (claims.bdh !== createHash("sha256").update(body).digest("base64url"))
110
+ return problem(401, "unauthorized", "the body is not the one signed");
111
+ if (seenJti.has(claims.jti))
112
+ return problem(401, "unauthorized", "assertion already used");
113
+ seenJti.add(claims.jti);
114
+ return null;
115
+ }
116
+ async function route(method, path, query, body) {
117
+ const p = path.split("/").slice(3).map(decodeURIComponent); // after /tenant/v0
118
+ const [a, b, c, d] = p;
119
+ if (a === "engine")
120
+ return ok(state.engine);
121
+ if (a === "key") {
122
+ const k = o.key ? parseTenantKey(o.key) : { slug: "acme", kid: "0123456789abcdef" };
123
+ return ok({ id: k.kid, name: "Test key", tenant: k.slug, scopes, created_at: "2026-11-01T00:00:00.000Z", expires_at: new Date(now() + 120 * 86_400_000).toISOString(), ...o.keyRecord });
124
+ }
125
+ if (a === "definitions" && b === "status")
126
+ return ok(state.definitions);
127
+ if (a === "definitions" && method === "POST") {
128
+ if (state.definitions.source !== "repository")
129
+ return problem(409, "definitions-not-repository", "the Definitions are edited in the Admin UI");
130
+ const hash = await definitionSetHash(body ?? {});
131
+ if (hash === state.definitions.hash)
132
+ return ok({ status: "unchanged", hash, revision: state.definitions.revision });
133
+ if (typeof submit === "function")
134
+ return ok(submit(body, hash));
135
+ if (submit === "wait") {
136
+ const plan_id = `plan-${hash.slice(0, 8)}`;
137
+ if (!state.definitions.waiting.some((w) => w.hash === hash))
138
+ state.definitions.waiting.push({ plan_id, hash, created_at: iso() });
139
+ return ok({ status: "waiting", hash, revision: state.definitions.revision, plan_id, summary: { changes: 1, unsafe: 1 }, changes: [{ address: "wallet:example", kind: "wallet", change: "label", effect: "repins", safe: false }], approve_url: `https://admin.example/tenants/acme?tab=definitions&plan=${plan_id}` });
140
+ }
141
+ state.definitions = { ...state.definitions, revision: state.definitions.revision + 1, hash, waiting: [] };
142
+ return ok({ status: "applied", hash, revision: state.definitions.revision, summary: { changes: 1, unsafe: 0 }, changes: [{ address: "wallet:example", kind: "wallet", change: "registered", effect: "creates", safe: true }] });
143
+ }
144
+ for (const tab of ["branding", "portal"]) {
145
+ if (a !== tab)
146
+ continue;
147
+ if (method === "GET")
148
+ return ok(tab === "branding" ? state.branding : state.portal);
149
+ if (state[tab].source !== "repository")
150
+ return problem(409, `${tab}-not-repository`, `the ${tab === "branding" ? "Branding" : "Portal"} tab is edited in the Admin UI`);
151
+ if (tab === "branding") {
152
+ const same = JSON.stringify(state.branding.branding) === JSON.stringify(body);
153
+ state.branding.branding = body;
154
+ return ok({ status: same ? "unchanged" : "applied" });
155
+ }
156
+ const next = { ...Object.fromEntries(ALL_SWITCHES.map((s) => [s, body[s] ?? true])), pages: { ...state.portal.portal.pages, ...(body.pages ?? {}) } };
157
+ const same = JSON.stringify(next) === JSON.stringify(state.portal.portal);
158
+ state.portal.portal = next;
159
+ const kept = state.portal.redirected.filter((pg) => body.pages?.[pg]);
160
+ return ok({ status: same ? "unchanged" : "applied", ...(kept.length ? { kept } : {}) });
161
+ }
162
+ if (a === "tiers") {
163
+ if (method === "GET")
164
+ return ok(state.tiers);
165
+ state.tiers = { ...state.tiers, ...body };
166
+ return ok({ status: "applied" });
167
+ }
168
+ if (a === "subscription")
169
+ return ok({ arid: null, tier: "starter", label: "Starter", state: "active", frozen: false, renews: true, period_end: null, trial_end: null, allowance: { active_customers: 100, storage: 1_000_000_000 }, used: { active_customers: 3, storage: 0 }, overage: null, closing_at: null, features: null });
170
+ if (a === "customers" && c === "entitlement")
171
+ return ok({ customer: b, tier: body?.tier, billing: { status: body?.status ?? "active" } });
172
+ if (a === "customers" && c === "entitlements")
173
+ return ok({ customer: b, tier: null, features: {} });
174
+ if (a === "customers" && c === "tags") {
175
+ const tag = state.tags.find((t) => t.name === d);
176
+ if (!tag)
177
+ return problem(404, "not-found", "Not Found");
178
+ const set = state.customerTags.get(b) ?? new Set();
179
+ state.customerTags.set(b, set);
180
+ if (method === "PUT") {
181
+ const added = !set.has(d);
182
+ set.add(d);
183
+ return ok({ customer: b, tag: d, added });
184
+ }
185
+ const removed = set.delete(d);
186
+ return ok({ customer: b, tag: d, removed });
187
+ }
188
+ if (a === "tags" && !b)
189
+ return ok({ items: state.tags });
190
+ if (a === "tags" && b) {
191
+ const existing = state.tags.find((t) => t.name === b);
192
+ if (existing) {
193
+ Object.assign(existing, body, { updated_at: iso() });
194
+ return ok({ ...existing, created: false });
195
+ }
196
+ const made = { id: `tag-${b}`, name: b, shown: `acme:${b}`, scope: "tenant", subject: "customer", visibility: body?.visibility ?? "staff", description: body?.description ?? "", colour: body?.colour ?? "slate", rules: body?.rules ?? [], effects: body?.effects ?? [], system: false, subjects: 0, created_at: iso(), updated_at: iso() };
197
+ state.tags.push(made);
198
+ return ok({ ...made, created: true }, 201);
199
+ }
200
+ if (a === "changesets" && !b) {
201
+ const since = Number(query.get("since") ?? 0) || 0;
202
+ return ok({ latest: state.engine.latest_changeset || (state.changesets.at(-1)?.number ?? 0), changesets: state.changesets.filter((x) => x.number > since) });
203
+ }
204
+ if (a === "changesets" && c === "status") {
205
+ const cs = state.changesets.find((x) => x.number === Number(b));
206
+ if (!cs || !cs.ticket)
207
+ return problem(404, "not-found", "Not Found");
208
+ if (body?.status === "canceled" && !body.reason)
209
+ return problem(422, "unprocessable", "a canceled changeset needs a reason");
210
+ cs.status = body?.status;
211
+ return ok(cs);
212
+ }
213
+ if (a === "feedback" && !b && method === "POST") {
214
+ state.reports.push(body);
215
+ const arid = id("tkt");
216
+ state.feedback.push(ticket({ arid, subject: body.summary, body: body.detail, primary: "feedback", at: iso() }));
217
+ return ok({ id: arid, received_at: iso() }, 201);
218
+ }
219
+ if (a === "feedback" && !b)
220
+ return ok({ items: state.feedback, next: state.feedback.length ? iso() : null });
221
+ if (a === "feedback" && c === "posts") {
222
+ const t = state.feedback.find((x) => x.arid === b);
223
+ if (!t)
224
+ return problem(404, "not-found", "Not Found");
225
+ t.posts.push(post(iso(), body.body, true, "Your servers"));
226
+ return ok(t, 201);
227
+ }
228
+ if (a === "tickets" && !b && method === "GET") {
229
+ const status = query.get("status");
230
+ return ok({ items: state.tickets.filter((t) => !status || t.status === status).map(({ parties: _p, posts: _q, links: _l, refs: _r, audience: _a, hold_until: _h, closed_at: _c, can: _k, ...summary }) => summary) });
231
+ }
232
+ if (a === "tickets" && !b && method === "POST") {
233
+ if (body?.to !== "platform" && !/^ARID:0:[a-z0-9-]+:cst:/.test(body?.to ?? ""))
234
+ return problem(422, "unprocessable", "to is platform or a Customer of this Tenant");
235
+ const t = ticket({ arid: id("tkt"), subject: body.subject, body: body.body, direction: body.to === "platform" ? "tenant_platform" : "tenant_customer", at: iso(), with_label: body.to === "platform" ? "Asturiu" : (body.to_name ?? "A Customer") });
236
+ state.tickets.push(t);
237
+ return ok(t, 201);
238
+ }
239
+ for (const [family, list] of [["tickets", state.tickets], ["announcements", state.announcements]]) {
240
+ if (a !== family || !b)
241
+ continue;
242
+ const t = list.find((x) => x.arid === b);
243
+ if (!t)
244
+ return problem(404, "not-found", "Not Found");
245
+ if (method === "GET")
246
+ return ok(t);
247
+ if (method === "PATCH") {
248
+ if (body?.status)
249
+ t.status = body.status;
250
+ if (body?.priority)
251
+ t.priority = body.priority;
252
+ if (body?.archived !== undefined)
253
+ t.archived = body.archived;
254
+ t.updated_at = iso();
255
+ return ok(t);
256
+ }
257
+ if (method === "POST" && c === "posts") {
258
+ t.posts.push(post(iso(), body.body, true, "Your servers"));
259
+ return ok(t, 201);
260
+ }
261
+ if (method === "DELETE") {
262
+ if (t.status !== "draft")
263
+ return problem(409, "conflict", "only a draft is deleted; withdraw a published announcement");
264
+ state.announcements.splice(state.announcements.indexOf(t), 1);
265
+ return new Response(null, { status: 204 });
266
+ }
267
+ }
268
+ if (a === "announcements" && method === "GET")
269
+ return ok({ items: state.announcements, platform: state.platform });
270
+ if (a === "announcements" && method === "POST") {
271
+ const t = ticket({ arid: id("tkt"), subject: body.subject, body: body.body ?? "", status: "draft", primary: "announcement", direction: "tenant_customers", at: iso(), with_label: "Customers" });
272
+ state.announcements.push(t);
273
+ return ok(t, 201);
274
+ }
275
+ return problem(404, "not-found", "Not Found");
276
+ }
277
+ async function handle(request) {
278
+ const url = new URL(request.url);
279
+ const body = request.method === "GET" || request.method === "HEAD" ? "" : await request.text();
280
+ const record = (status) => calls.push({ method: request.method, path: url.pathname, query: url.search, body: body ? safeJson(body) : undefined, status, sdk_version: /(?:^|\s)asturiu-v0-sdk\/(\S+)/.exec(request.headers.get("user-agent") ?? "")?.[1] ?? null });
281
+ // The Engine site's documents.
282
+ if (!url.pathname.startsWith("/tenant/v0/")) {
283
+ const doc = o.documents?.[url.href];
284
+ record(doc === undefined ? 404 : 200);
285
+ return doc === undefined ? new Response("Not Found", { status: 404 }) : new Response(doc, { status: 200, headers: { "content-type": "text/markdown; charset=utf-8" } });
286
+ }
287
+ const respond = (r) => {
288
+ record(r.status);
289
+ return r;
290
+ };
291
+ if (o.refuse)
292
+ return respond(problem(o.refuse, o.refuse === 401 ? "unauthorized" : "refused", o.refuse === 401 ? "the key was refused" : "refused"));
293
+ const m = matchTenantApiRoute(request.method, url.pathname);
294
+ if (!m || o.missing?.includes(`${m.route.method} ${m.route.path}`))
295
+ return respond(problem(404, "not-found", "Not Found"));
296
+ const refused = refuseAssertion(request.headers, request.method, url.pathname, body);
297
+ if (refused)
298
+ return respond(refused);
299
+ if (!keyReachesRoute(scopes, m.route))
300
+ return respond(problem(404, "not-found", "Not Found"));
301
+ return respond(await route(request.method, url.pathname, url.searchParams, body ? safeJson(body) : undefined));
302
+ }
303
+ const fetch = async (input, init) => {
304
+ if (o.down) {
305
+ const code = typeof o.down === "string" ? o.down : "ECONNREFUSED";
306
+ throw Object.assign(new TypeError("fetch failed"), { cause: Object.assign(new Error(code), { code }) });
307
+ }
308
+ return handle(new Request(input, init));
309
+ };
310
+ return { fetch, handle, state, calls, routes: TENANT_API_ROUTES };
311
+ }
312
+ function safeJson(text) {
313
+ try {
314
+ return JSON.parse(text);
315
+ }
316
+ catch {
317
+ return text;
318
+ }
319
+ }
320
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"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"}