@pwfabric/cli 0.0.0-stage → 1.0.0-rc.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 (171) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +122 -2
  3. package/dist/args.d.ts +12 -0
  4. package/dist/args.d.ts.map +1 -0
  5. package/dist/args.js +43 -0
  6. package/dist/args.js.map +1 -0
  7. package/dist/bin.d.ts +3 -0
  8. package/dist/bin.d.ts.map +1 -0
  9. package/dist/bin.js +10 -0
  10. package/dist/bin.js.map +1 -0
  11. package/dist/commands/add.d.ts +4 -0
  12. package/dist/commands/add.d.ts.map +1 -0
  13. package/dist/commands/add.js +56 -0
  14. package/dist/commands/add.js.map +1 -0
  15. package/dist/commands/build.d.ts +4 -0
  16. package/dist/commands/build.d.ts.map +1 -0
  17. package/dist/commands/build.js +55 -0
  18. package/dist/commands/build.js.map +1 -0
  19. package/dist/commands/create.d.ts +10 -0
  20. package/dist/commands/create.d.ts.map +1 -0
  21. package/dist/commands/create.js +119 -0
  22. package/dist/commands/create.js.map +1 -0
  23. package/dist/commands/dev.d.ts +13 -0
  24. package/dist/commands/dev.d.ts.map +1 -0
  25. package/dist/commands/dev.js +107 -0
  26. package/dist/commands/dev.js.map +1 -0
  27. package/dist/commands/lib/flags.d.ts +11 -0
  28. package/dist/commands/lib/flags.d.ts.map +1 -0
  29. package/dist/commands/lib/flags.js +33 -0
  30. package/dist/commands/lib/flags.js.map +1 -0
  31. package/dist/commands/lib/identity.d.ts +39 -0
  32. package/dist/commands/lib/identity.d.ts.map +1 -0
  33. package/dist/commands/lib/identity.js +120 -0
  34. package/dist/commands/lib/identity.js.map +1 -0
  35. package/dist/commands/lib/project.d.ts +35 -0
  36. package/dist/commands/lib/project.d.ts.map +1 -0
  37. package/dist/commands/lib/project.js +78 -0
  38. package/dist/commands/lib/project.js.map +1 -0
  39. package/dist/commands/lib/report.d.ts +16 -0
  40. package/dist/commands/lib/report.d.ts.map +1 -0
  41. package/dist/commands/lib/report.js +75 -0
  42. package/dist/commands/lib/report.js.map +1 -0
  43. package/dist/commands/lib/starter.d.ts +42 -0
  44. package/dist/commands/lib/starter.d.ts.map +1 -0
  45. package/dist/commands/lib/starter.js +136 -0
  46. package/dist/commands/lib/starter.js.map +1 -0
  47. package/dist/commands/lib/static-server.d.ts +46 -0
  48. package/dist/commands/lib/static-server.d.ts.map +1 -0
  49. package/dist/commands/lib/static-server.js +173 -0
  50. package/dist/commands/lib/static-server.js.map +1 -0
  51. package/dist/commands/pack.d.ts +6 -0
  52. package/dist/commands/pack.d.ts.map +1 -0
  53. package/dist/commands/pack.js +56 -0
  54. package/dist/commands/pack.js.map +1 -0
  55. package/dist/commands/registry.d.ts +8 -0
  56. package/dist/commands/registry.d.ts.map +1 -0
  57. package/dist/commands/registry.js +16 -0
  58. package/dist/commands/registry.js.map +1 -0
  59. package/dist/commands/run.d.ts +15 -0
  60. package/dist/commands/run.d.ts.map +1 -0
  61. package/dist/commands/run.js +79 -0
  62. package/dist/commands/run.js.map +1 -0
  63. package/dist/commands/types.d.ts +35 -0
  64. package/dist/commands/types.d.ts.map +1 -0
  65. package/dist/commands/types.js +10 -0
  66. package/dist/commands/types.js.map +1 -0
  67. package/dist/commands/validate.d.ts +7 -0
  68. package/dist/commands/validate.d.ts.map +1 -0
  69. package/dist/commands/validate.js +33 -0
  70. package/dist/commands/validate.js.map +1 -0
  71. package/dist/dev/assemble.d.ts +48 -0
  72. package/dist/dev/assemble.d.ts.map +1 -0
  73. package/dist/dev/assemble.js +339 -0
  74. package/dist/dev/assemble.js.map +1 -0
  75. package/dist/dev/compile.d.ts +55 -0
  76. package/dist/dev/compile.d.ts.map +1 -0
  77. package/dist/dev/compile.js +215 -0
  78. package/dist/dev/compile.js.map +1 -0
  79. package/dist/dev/csp.d.ts +68 -0
  80. package/dist/dev/csp.d.ts.map +1 -0
  81. package/dist/dev/csp.js +260 -0
  82. package/dist/dev/csp.js.map +1 -0
  83. package/dist/dev/diagnostics.d.ts +22 -0
  84. package/dist/dev/diagnostics.d.ts.map +1 -0
  85. package/dist/dev/diagnostics.js +22 -0
  86. package/dist/dev/diagnostics.js.map +1 -0
  87. package/dist/dev/envelope.d.ts +93 -0
  88. package/dist/dev/envelope.d.ts.map +1 -0
  89. package/dist/dev/envelope.js +154 -0
  90. package/dist/dev/envelope.js.map +1 -0
  91. package/dist/dev/media.d.ts +54 -0
  92. package/dist/dev/media.d.ts.map +1 -0
  93. package/dist/dev/media.js +128 -0
  94. package/dist/dev/media.js.map +1 -0
  95. package/dist/dev/needs-host.d.ts +3 -0
  96. package/dist/dev/needs-host.d.ts.map +1 -0
  97. package/dist/dev/needs-host.js +32 -0
  98. package/dist/dev/needs-host.js.map +1 -0
  99. package/dist/dev/output.d.ts +10 -0
  100. package/dist/dev/output.d.ts.map +1 -0
  101. package/dist/dev/output.js +32 -0
  102. package/dist/dev/output.js.map +1 -0
  103. package/dist/dev/overlay.d.ts +22 -0
  104. package/dist/dev/overlay.d.ts.map +1 -0
  105. package/dist/dev/overlay.js +59 -0
  106. package/dist/dev/overlay.js.map +1 -0
  107. package/dist/dev/server.d.ts +28 -0
  108. package/dist/dev/server.d.ts.map +1 -0
  109. package/dist/dev/server.js +264 -0
  110. package/dist/dev/server.js.map +1 -0
  111. package/dist/dev/shell.d.ts +83 -0
  112. package/dist/dev/shell.d.ts.map +1 -0
  113. package/dist/dev/shell.js +244 -0
  114. package/dist/dev/shell.js.map +1 -0
  115. package/dist/dev/sources.d.ts +46 -0
  116. package/dist/dev/sources.d.ts.map +1 -0
  117. package/dist/dev/sources.js +165 -0
  118. package/dist/dev/sources.js.map +1 -0
  119. package/dist/dev/theme.d.ts +52 -0
  120. package/dist/dev/theme.d.ts.map +1 -0
  121. package/dist/dev/theme.js +185 -0
  122. package/dist/dev/theme.js.map +1 -0
  123. package/dist/dev/types.d.ts +41 -0
  124. package/dist/dev/types.d.ts.map +1 -0
  125. package/dist/dev/types.js +11 -0
  126. package/dist/dev/types.js.map +1 -0
  127. package/dist/dev/watcher.d.ts +30 -0
  128. package/dist/dev/watcher.d.ts.map +1 -0
  129. package/dist/dev/watcher.js +150 -0
  130. package/dist/dev/watcher.js.map +1 -0
  131. package/dist/host/definitions.d.ts +62 -0
  132. package/dist/host/definitions.d.ts.map +1 -0
  133. package/dist/host/definitions.js +136 -0
  134. package/dist/host/definitions.js.map +1 -0
  135. package/dist/host/http.d.ts +40 -0
  136. package/dist/host/http.d.ts.map +1 -0
  137. package/dist/host/http.js +156 -0
  138. package/dist/host/http.js.map +1 -0
  139. package/dist/host/local-host.d.ts +60 -0
  140. package/dist/host/local-host.d.ts.map +1 -0
  141. package/dist/host/local-host.js +420 -0
  142. package/dist/host/local-host.js.map +1 -0
  143. package/dist/host/oidc.d.ts +47 -0
  144. package/dist/host/oidc.d.ts.map +1 -0
  145. package/dist/host/oidc.js +192 -0
  146. package/dist/host/oidc.js.map +1 -0
  147. package/dist/host/query.d.ts +36 -0
  148. package/dist/host/query.d.ts.map +1 -0
  149. package/dist/host/query.js +158 -0
  150. package/dist/host/query.js.map +1 -0
  151. package/dist/host/receipts.d.ts +26 -0
  152. package/dist/host/receipts.d.ts.map +1 -0
  153. package/dist/host/receipts.js +72 -0
  154. package/dist/host/receipts.js.map +1 -0
  155. package/dist/host/records.d.ts +74 -0
  156. package/dist/host/records.d.ts.map +1 -0
  157. package/dist/host/records.js +229 -0
  158. package/dist/host/records.js.map +1 -0
  159. package/dist/host/tokens.d.ts +29 -0
  160. package/dist/host/tokens.d.ts.map +1 -0
  161. package/dist/host/tokens.js +52 -0
  162. package/dist/host/tokens.js.map +1 -0
  163. package/dist/host/types.d.ts +33 -0
  164. package/dist/host/types.d.ts.map +1 -0
  165. package/dist/host/types.js +11 -0
  166. package/dist/host/types.js.map +1 -0
  167. package/dist/index.d.ts +17 -0
  168. package/dist/index.d.ts.map +1 -0
  169. package/dist/index.js +41 -0
  170. package/dist/index.js.map +1 -0
  171. package/package.json +65 -3
@@ -0,0 +1,420 @@
1
+ /**
2
+ * The local host — the session protocol and the data protocol, in process,
3
+ * for development.
4
+ *
5
+ * NOT A PRODUCTION SERVER. Records live in memory and vanish on restart; the
6
+ * one development user signs in without a password; the issuer stand-in mints
7
+ * unsigned ID tokens; there is no rate limit, no CORS, no TLS. It exists so an
8
+ * app that declares data and sign-in runs on a laptop with no hosted service,
9
+ * and so the runner's sign-in wall, account control, gate and data paths are
10
+ * exercised against the same addresses and answers a session server gives.
11
+ *
12
+ * Everything is mounted under `prefix` (e.g. `/_host`); `<base>` below is
13
+ * `<origin><prefix>`, which is also the app's own API base the runner derives
14
+ * from `loginUrl` (session-protocol §2).
15
+ *
16
+ * App door (session-protocol §4, §8)
17
+ * POST <base>/login, <base>/register any credentials → the development user
18
+ * POST <base>/logout revokes the presented token
19
+ * GET <base>/session the principal behind the token
20
+ * GET <base>/_auth/start/<method> provider sign-in, through the same redirects
21
+ * GET <base>/_auth/callback/<method> …ends here: HttpOnly cookie, back to returnTo
22
+ * GET <base>/_auth/session the cookie's session (needs x-pwapp-request: 1)
23
+ * POST <base>/_auth/logout deletes the cookie (needs x-pwapp-request: 1)
24
+ * External issuer stand-in (session-protocol §3) — see ./oidc.ts
25
+ * GET <base>/oidc/.well-known/openid-configuration, GET <base>/oidc/authorize,
26
+ * POST <base>/oidc/token
27
+ * Records (data-protocol §5) — see ./records.ts
28
+ * GET|POST <base>/records/<T>, GET <base>/records/<T>/count, GET <base>/records/<T>/aggregate,
29
+ * GET|PATCH|DELETE <base>/records/<T>/<id>
30
+ * Pages
31
+ * GET <base>/surfaces/<key>.receipt.json the receipt, entity sources rewritten to <base>,
32
+ * refused without a session when sign-in is required
33
+ *
34
+ * Every credential is accepted on `x-app-session` or `Authorization: Bearer`.
35
+ * Tokens are opaque and random, kept only as hashes, and never logged.
36
+ */
37
+ import { HostError, cookiesOf, credentialOf, readJsonObject, redirect, safeReturnTo, sendError, sendJson, } from './http.js';
38
+ import { readAuth, readEntities, readReceipt, surfaceKeys, } from './definitions.js';
39
+ import { RecordStore } from './records.js';
40
+ import { rewriteEntitySources } from './receipts.js';
41
+ import { DevIssuer } from './oidc.js';
42
+ import { TokenStore } from './tokens.js';
43
+ export const DEFAULT_DEV_USER = { id: 'dev-user', name: 'Developer', email: 'dev@localhost' };
44
+ /** The cookie the provider round trip leaves on the app's origin. */
45
+ export const SESSION_COOKIE = 'pwf_dev_session';
46
+ const SESSION_TTL_MS = 8 * 3600_000;
47
+ const TRANSACTION_TTL_MS = 5 * 60_000;
48
+ /** The provider buttons a session server can name (envelope `auth.json` `providers[].method`). */
49
+ const PROVIDER_METHODS = new Set(['host', 'google', 'github', 'microsoft']);
50
+ function normalisePrefix(prefix) {
51
+ const trimmed = prefix.replace(/^\/+|\/+$/g, '');
52
+ if (!trimmed)
53
+ throw new Error('createLocalHost: prefix must name a path, e.g. "/_host"');
54
+ return `/${trimmed}`;
55
+ }
56
+ function providersOf(auth) {
57
+ return auth.methods.filter((m) => PROVIDER_METHODS.has(m));
58
+ }
59
+ /**
60
+ * The envelope `auth.json` for this declaration, pointed at `base` — the
61
+ * same shape a publisher writes (session-protocol §2), or `undefined` when the
62
+ * app has no way in.
63
+ *
64
+ * - `external`: `oauth2-pkce` against the local issuer stand-in, keeping the
65
+ * declared client id, scopes (plus `offline_access`, which is what makes a
66
+ * refresh token exist) and audience.
67
+ * - `app`: the password door when `password` is declared; the provider
68
+ * buttons and the start address for every declared provider method; the
69
+ * gateway's session and logout addresses for either; `methods` as declared.
70
+ */
71
+ export function authAddresses(auth, base) {
72
+ if (!auth)
73
+ return undefined;
74
+ if (auth.topology === 'external') {
75
+ if (!auth.issuer)
76
+ return undefined;
77
+ const scopes = auth.issuer.scopes.includes('offline_access')
78
+ ? [...auth.issuer.scopes]
79
+ : [...auth.issuer.scopes, 'offline_access'];
80
+ return {
81
+ provider: 'oauth2-pkce',
82
+ issuer: `${base}/oidc`,
83
+ clientId: auth.issuer.clientId,
84
+ scopes,
85
+ ...(auth.issuer.audience ? { audience: auth.issuer.audience } : {}),
86
+ };
87
+ }
88
+ const door = {};
89
+ if (auth.methods.includes('password')) {
90
+ door.provider = 'password';
91
+ door.loginUrl = `${base}/login`;
92
+ door.registerUrl = `${base}/register`;
93
+ door.logoutUrl = `${base}/logout`;
94
+ door.sessionUrl = `${base}/session`;
95
+ }
96
+ const providers = providersOf(auth);
97
+ if (providers.length > 0) {
98
+ door.provider = door.provider ?? 'platform';
99
+ door.providers = providers.map((method) => ({ method }));
100
+ door.startUrl = `${base}/_auth/start`;
101
+ door.gatewaySessionUrl = `${base}/_auth/session`;
102
+ door.gatewayLogoutUrl = `${base}/_auth/logout`;
103
+ }
104
+ if (Object.keys(door).length === 0)
105
+ return undefined;
106
+ // The runner asks the gateway on every app door, not only a provider one:
107
+ // for a stored-nothing session on boot, and on every sign-out (it falls back
108
+ // to `/_auth/session` and `/_auth/logout` at the page's origin, which on
109
+ // `pwf dev` are not the host's). The host answers both under its base.
110
+ door.gatewaySessionUrl ??= `${base}/_auth/session`;
111
+ door.gatewayLogoutUrl ??= `${base}/_auth/logout`;
112
+ door.methods = [...auth.methods];
113
+ return door;
114
+ }
115
+ function segments(rest) {
116
+ try {
117
+ return rest.split('/').filter(Boolean).map((s) => decodeURIComponent(s));
118
+ }
119
+ catch {
120
+ throw new HostError(400, 'INVALID_PATH', 'The path is not valid percent-encoding.');
121
+ }
122
+ }
123
+ function methodNotAllowed() {
124
+ throw new HostError(405, 'METHOD_NOT_ALLOWED', 'This route does not take that method.');
125
+ }
126
+ function notFound() {
127
+ throw new HostError(404, 'NOT_FOUND', 'No such route on the local host.');
128
+ }
129
+ export const createLocalHost = (options) => {
130
+ const root = options.root;
131
+ const prefix = normalisePrefix(options.prefix);
132
+ const user = {
133
+ id: options.user?.id ?? DEFAULT_DEV_USER.id,
134
+ email: options.user?.email ?? DEFAULT_DEV_USER.email,
135
+ displayName: options.user?.name ?? DEFAULT_DEV_USER.name,
136
+ };
137
+ const bearer = new TokenStore();
138
+ const transactions = new TokenStore();
139
+ const records = new RecordStore(root, user);
140
+ const issuer = new DevIssuer(bearer, user);
141
+ const originOf = (req) => `http://${req.headers.host ?? 'localhost'}`;
142
+ const principalOf = (req) => bearer.get(credentialOf(req))?.principal;
143
+ function startSession() {
144
+ const expiresAt = Date.now() + SESSION_TTL_MS;
145
+ const token = bearer.issue({ principal: user, kind: 'session', expiresAt });
146
+ return { token, expiresAt: new Date(expiresAt).toISOString(), principal: user };
147
+ }
148
+ const sessionCookie = (token, maxAgeS) => `${SESSION_COOKIE}=${encodeURIComponent(token)}; Path=${prefix}/_auth; HttpOnly; SameSite=Lax; Max-Age=${maxAgeS}`;
149
+ function requireRunnerRequest(req) {
150
+ if (req.headers['x-pwapp-request'] !== '1') {
151
+ throw new HostError(403, 'RUNNER_REQUEST_REQUIRED', 'This address answers only the runner (x-pwapp-request: 1).');
152
+ }
153
+ }
154
+ // ---------------------------------------------------------------- app door
155
+ async function door(req, res, action) {
156
+ const auth = readAuth(root);
157
+ if (action === 'session') {
158
+ if (req.method !== 'GET')
159
+ methodNotAllowed();
160
+ const presented = credentialOf(req);
161
+ const grant = bearer.get(presented);
162
+ if (grant) {
163
+ sendJson(res, 200, { data: { principal: grant.principal } });
164
+ return;
165
+ }
166
+ if (presented !== undefined || auth?.required) {
167
+ throw new HostError(401, 'SIGN_IN_REQUIRED', 'No live session.');
168
+ }
169
+ sendJson(res, 200, { data: { principal: null } });
170
+ return;
171
+ }
172
+ if (req.method !== 'POST')
173
+ methodNotAllowed();
174
+ if (action === 'logout') {
175
+ bearer.revoke(credentialOf(req));
176
+ sendJson(res, 200, { data: { signedOut: true } });
177
+ return;
178
+ }
179
+ // login / register: the credentials are read (and must be JSON) but not
180
+ // checked — the development user has no password.
181
+ await readJsonObject(req);
182
+ if (!auth || auth.topology !== 'app' || !auth.methods.includes('password')) {
183
+ throw new HostError(404, 'NO_PASSWORD_DOOR', 'This app declares no password sign-in.');
184
+ }
185
+ sendJson(res, action === 'register' ? 201 : 200, { data: startSession() });
186
+ }
187
+ function gateway(req, res, url, parts) {
188
+ const [action, method] = parts;
189
+ if (action === 'start' || action === 'callback') {
190
+ if (req.method !== 'GET')
191
+ methodNotAllowed();
192
+ if (parts.length !== 2 || !method)
193
+ notFound();
194
+ if (action === 'start') {
195
+ const returnTo = safeReturnTo(url.searchParams.get('returnTo'));
196
+ const auth = readAuth(root);
197
+ if (!auth || auth.topology !== 'app' || !providersOf(auth).includes(method)) {
198
+ redirect(res, withAuthError(returnTo, 'provider_unavailable'));
199
+ return;
200
+ }
201
+ // The provider's own leg is played by the callback below: the browser
202
+ // still leaves the app, comes back to the callback, and lands on returnTo.
203
+ const tx = transactions.issue({ returnTo, method, expiresAt: Date.now() + TRANSACTION_TTL_MS });
204
+ redirect(res, `${prefix}/_auth/callback/${encodeURIComponent(method)}?tx=${encodeURIComponent(tx)}`);
205
+ return;
206
+ }
207
+ const tx = transactions.take(url.searchParams.get('tx') ?? undefined);
208
+ if (!tx || tx.method !== method) {
209
+ redirect(res, withAuthError('/', 'invalid_transaction'));
210
+ return;
211
+ }
212
+ const session = startSession();
213
+ redirect(res, tx.returnTo, [sessionCookie(session.token, SESSION_TTL_MS / 1000)]);
214
+ return;
215
+ }
216
+ if (parts.length !== 1)
217
+ notFound();
218
+ if (action === 'session') {
219
+ if (req.method !== 'GET')
220
+ methodNotAllowed();
221
+ requireRunnerRequest(req);
222
+ const token = cookiesOf(req)[SESSION_COOKIE];
223
+ const grant = bearer.get(token);
224
+ if (!token || !grant || grant.kind !== 'session') {
225
+ throw new HostError(401, 'SIGN_IN_REQUIRED', 'No session cookie.');
226
+ }
227
+ sendJson(res, 200, {
228
+ data: { token, expiresAt: new Date(grant.expiresAt).toISOString(), principal: grant.principal },
229
+ });
230
+ return;
231
+ }
232
+ if (action === 'logout') {
233
+ if (req.method !== 'POST')
234
+ methodNotAllowed();
235
+ requireRunnerRequest(req);
236
+ bearer.revoke(cookiesOf(req)[SESSION_COOKIE]);
237
+ sendJson(res, 200, { data: { signedOut: true } }, { 'set-cookie': sessionCookie('', 0) });
238
+ return;
239
+ }
240
+ notFound();
241
+ }
242
+ // ------------------------------------------------------------------ issuer
243
+ async function oidc(req, res, url, parts) {
244
+ const auth = readAuth(root);
245
+ if (!auth || auth.topology !== 'external' || !auth.issuer) {
246
+ throw new HostError(404, 'NO_ISSUER', 'This app declares no external issuer.');
247
+ }
248
+ const iss = DevIssuer.issuerUrl(originOf(req), prefix);
249
+ const route = parts.join('/');
250
+ if (route === '.well-known/openid-configuration') {
251
+ if (req.method !== 'GET')
252
+ methodNotAllowed();
253
+ issuer.discovery(res, iss);
254
+ return;
255
+ }
256
+ if (route === 'authorize') {
257
+ if (req.method !== 'GET')
258
+ methodNotAllowed();
259
+ issuer.authorize(req, res, url, auth);
260
+ return;
261
+ }
262
+ if (route === 'token') {
263
+ if (req.method !== 'POST')
264
+ methodNotAllowed();
265
+ await issuer.token(req, res, iss, auth);
266
+ return;
267
+ }
268
+ notFound();
269
+ }
270
+ // ----------------------------------------------------------------- records
271
+ function entityOf(typeId) {
272
+ const entity = readEntities(root).find((e) => e.typeId === typeId);
273
+ if (!entity)
274
+ throw new HostError(404, 'UNKNOWN_ENTITY_TYPE', `The app declares no entity type "${typeId}".`);
275
+ return entity;
276
+ }
277
+ async function data(req, res, url, parts) {
278
+ const [typeId, second] = parts;
279
+ if (!typeId || parts.length > 2)
280
+ notFound();
281
+ const target = { entity: entityOf(typeId), auth: readAuth(root), caller: { principal: principalOf(req) } };
282
+ const params = url.searchParams;
283
+ if (second === undefined) {
284
+ if (req.method === 'GET') {
285
+ sendJson(res, 200, records.list(target, params));
286
+ return;
287
+ }
288
+ if (req.method === 'POST') {
289
+ const record = records.create(target, await readJsonObject(req));
290
+ sendJson(res, 201, { id: record.id, data: record });
291
+ return;
292
+ }
293
+ methodNotAllowed();
294
+ }
295
+ if (second === 'count' || second === 'aggregate') {
296
+ if (req.method !== 'GET')
297
+ methodNotAllowed();
298
+ sendJson(res, 200, records.aggregate(target, params, second === 'count'));
299
+ return;
300
+ }
301
+ if (req.method === 'GET') {
302
+ const record = records.read(target, second);
303
+ sendJson(res, 200, { id: record.id, data: record });
304
+ return;
305
+ }
306
+ if (req.method === 'PATCH') {
307
+ const record = records.update(target, second, await readJsonObject(req));
308
+ sendJson(res, 200, { id: record.id, data: record });
309
+ return;
310
+ }
311
+ if (req.method === 'DELETE') {
312
+ records.remove(target, second);
313
+ sendJson(res, 200, { data: { id: second, deleted: true } });
314
+ return;
315
+ }
316
+ methodNotAllowed();
317
+ }
318
+ // ------------------------------------------------------------------- pages
319
+ function receiptFor(key, base) {
320
+ const receipt = readReceipt(root, key);
321
+ if (!receipt)
322
+ return undefined;
323
+ return rewriteEntitySources(receipt, base, new Set(readEntities(root).map((e) => e.typeId)));
324
+ }
325
+ function surface(req, res, parts) {
326
+ if (req.method !== 'GET')
327
+ methodNotAllowed();
328
+ const file = parts.length === 1 ? parts[0] : undefined;
329
+ if (!file || !file.endsWith('.receipt.json'))
330
+ notFound();
331
+ if (readAuth(root)?.required && !principalOf(req)) {
332
+ throw new HostError(401, 'SIGN_IN_REQUIRED', 'Sign in to open this page.');
333
+ }
334
+ const receipt = receiptFor(file.slice(0, -'.receipt.json'.length), originOf(req) + prefix);
335
+ if (!receipt)
336
+ notFound();
337
+ sendJson(res, 200, receipt);
338
+ }
339
+ // ------------------------------------------------------------------ router
340
+ async function route(req, res, url, rest) {
341
+ const [head, ...tail] = segments(rest);
342
+ switch (head) {
343
+ case 'login':
344
+ case 'register':
345
+ case 'logout':
346
+ case 'session':
347
+ if (tail.length > 0)
348
+ notFound();
349
+ return door(req, res, head);
350
+ case '_auth':
351
+ return gateway(req, res, url, tail);
352
+ case 'oidc':
353
+ return oidc(req, res, url, tail);
354
+ case 'records':
355
+ return data(req, res, url, tail);
356
+ case 'surfaces':
357
+ return surface(req, res, tail);
358
+ default:
359
+ notFound();
360
+ }
361
+ }
362
+ return {
363
+ envelopeEntries(origin) {
364
+ const base = origin.replace(/\/+$/, '') + prefix;
365
+ const out = {};
366
+ const auth = authAddresses(readAuth(root), base);
367
+ if (auth)
368
+ out['auth.json'] = auth;
369
+ for (const key of surfaceKeys(root)) {
370
+ const receipt = receiptFor(key, base);
371
+ if (receipt)
372
+ out[`surfaces/${key}.receipt.json`] = receipt;
373
+ }
374
+ return out;
375
+ },
376
+ async handle(req, res) {
377
+ let url;
378
+ try {
379
+ url = new URL(req.url ?? '/', 'http://localhost');
380
+ }
381
+ catch {
382
+ return false;
383
+ }
384
+ const path = url.pathname;
385
+ if (path !== prefix && !path.startsWith(`${prefix}/`))
386
+ return false;
387
+ try {
388
+ await route(req, res, url, path.slice(prefix.length));
389
+ }
390
+ catch (err) {
391
+ if (res.headersSent) {
392
+ res.end();
393
+ }
394
+ else if (err instanceof HostError) {
395
+ sendError(res, err);
396
+ }
397
+ else {
398
+ // A broken definition file is the developer's to fix; say which.
399
+ sendError(res, new HostError(500, 'HOST_ERROR', err instanceof Error ? err.message : String(err)));
400
+ }
401
+ }
402
+ return true;
403
+ },
404
+ reset() {
405
+ records.reset();
406
+ bearer.clear();
407
+ transactions.clear();
408
+ issuer.reset();
409
+ },
410
+ };
411
+ };
412
+ function withAuthError(returnTo, code) {
413
+ const [path, hash] = splitHash(returnTo);
414
+ return `${path}${path.includes('?') ? '&' : '?'}auth_error=${encodeURIComponent(code)}${hash}`;
415
+ }
416
+ function splitHash(value) {
417
+ const at = value.indexOf('#');
418
+ return at === -1 ? [value, ''] : [value.slice(0, at), value.slice(at)];
419
+ }
420
+ //# sourceMappingURL=local-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-host.js","sourceRoot":"","sources":["../../src/host/local-host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * A development stand-in for an external OpenID Connect issuer.
3
+ *
4
+ * When `auth.json` declares `topology: "external"`, the app's real issuer
5
+ * cannot be reached from a laptop without registering a redirect URI for
6
+ * every port `pwf dev` picks. The local host therefore plays that issuer, at
7
+ * `<prefix>/oidc`, with just enough of the protocol for the runner's PKCE
8
+ * client (session-protocol §3):
9
+ *
10
+ * GET <prefix>/oidc/.well-known/openid-configuration discovery
11
+ * GET <prefix>/oidc/authorize code + PKCE (S256), no consent screen:
12
+ * the development user is signed in at once
13
+ * POST <prefix>/oidc/token authorization_code, refresh_token
14
+ * (and refresh_token + scope "<audience>/.default"
15
+ * for the door token)
16
+ *
17
+ * The declared `clientId`, scopes and audience are kept; only the issuer
18
+ * address changes. Tokens are opaque; the ID token is an UNSIGNED JWT
19
+ * (`alg: none`), which the runner decodes and does not verify. No real
20
+ * issuer's keys are ever involved, and nothing here is safe to expose beyond
21
+ * the developer's own machine.
22
+ */
23
+ import type { IncomingMessage, ServerResponse } from 'node:http';
24
+ import type { AuthDeclaration } from './definitions.js';
25
+ import { TokenStore, type Principal } from './tokens.js';
26
+ /** What a bearer credential stands for, whichever door minted it. */
27
+ export interface Grant {
28
+ readonly principal: Principal;
29
+ readonly expiresAt: number;
30
+ readonly kind: 'session' | 'access' | 'door';
31
+ }
32
+ export declare const ACCESS_TTL_S = 3600;
33
+ export declare class DevIssuer {
34
+ private readonly bearer;
35
+ private readonly user;
36
+ private readonly codes;
37
+ private readonly refresh;
38
+ constructor(bearer: TokenStore<Grant>, user: Principal);
39
+ reset(): void;
40
+ /** `<origin><prefix>/oidc` — the `iss` this issuer speaks for. */
41
+ static issuerUrl(origin: string, prefix: string): string;
42
+ discovery(res: ServerResponse, issuer: string): void;
43
+ authorize(req: IncomingMessage, res: ServerResponse, url: URL, auth: AuthDeclaration): void;
44
+ token(req: IncomingMessage, res: ServerResponse, issuer: string, auth: AuthDeclaration): Promise<void>;
45
+ private mint;
46
+ }
47
+ //# sourceMappingURL=oidc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc.d.ts","sourceRoot":"","sources":["../../src/host/oidc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAEhE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAA;AAExD,qEAAqE;AACrE,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAA;CAC7C;AAkBD,eAAO,MAAM,YAAY,OAAO,CAAA;AAUhC,qBAAa,SAAS;IAKlB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IALvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8B;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;gBAGtC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,EACzB,IAAI,EAAE,SAAS;IAGlC,KAAK,IAAI,IAAI;IAKb,kEAAkE;IAClE,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAIxD,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAcpD,SAAS,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe,GAAG,IAAI;IA2CrF,KAAK,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAgD5G,OAAO,CAAC,IAAI;CA6Cb"}