@fuzdev/fuz_app 0.54.0 → 0.55.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.
- package/dist/actions/CLAUDE.md +68 -13
- package/dist/actions/action_codegen.d.ts +13 -0
- package/dist/actions/action_codegen.d.ts.map +1 -1
- package/dist/actions/action_codegen.js +15 -1
- package/dist/actions/action_rpc.d.ts +60 -7
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +158 -44
- package/dist/actions/register_action_ws.d.ts +4 -4
- package/dist/actions/register_action_ws.js +6 -6
- package/dist/actions/register_ws_endpoint.d.ts +20 -7
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +30 -5
- package/dist/actions/transports.d.ts.map +1 -1
- package/dist/actions/transports.js +0 -4
- package/dist/auth/CLAUDE.md +219 -66
- package/dist/auth/account_actions.d.ts +6 -6
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +8 -11
- package/dist/auth/account_queries.d.ts +6 -3
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_queries.js +14 -5
- package/dist/auth/account_routes.d.ts +7 -10
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +70 -23
- package/dist/auth/account_schema.d.ts +19 -0
- package/dist/auth/account_schema.d.ts.map +1 -1
- package/dist/auth/account_schema.js +20 -0
- package/dist/auth/admin_action_specs.d.ts +45 -11
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +23 -8
- package/dist/auth/admin_actions.d.ts +8 -7
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +11 -18
- package/dist/auth/audit_log_queries.d.ts +53 -14
- package/dist/auth/audit_log_queries.d.ts.map +1 -1
- package/dist/auth/audit_log_queries.js +45 -2
- package/dist/auth/audit_log_schema.d.ts +55 -1
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +19 -3
- package/dist/auth/bearer_auth.d.ts +9 -7
- package/dist/auth/bearer_auth.d.ts.map +1 -1
- package/dist/auth/bearer_auth.js +13 -21
- package/dist/auth/cleanup.d.ts.map +1 -1
- package/dist/auth/cleanup.js +5 -0
- package/dist/auth/daemon_token_middleware.d.ts +23 -11
- package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
- package/dist/auth/daemon_token_middleware.js +26 -20
- package/dist/auth/deps.d.ts +14 -0
- package/dist/auth/deps.d.ts.map +1 -1
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +4 -2
- package/dist/auth/migrations.d.ts +15 -7
- package/dist/auth/migrations.d.ts.map +1 -1
- package/dist/auth/migrations.js +15 -7
- package/dist/auth/permit_offer_action_specs.d.ts +45 -6
- package/dist/auth/permit_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/permit_offer_action_specs.js +38 -7
- package/dist/auth/permit_offer_actions.d.ts +2 -2
- package/dist/auth/permit_offer_actions.d.ts.map +1 -1
- package/dist/auth/permit_offer_actions.js +98 -90
- package/dist/auth/permit_offer_notifications.d.ts +10 -0
- package/dist/auth/permit_offer_notifications.d.ts.map +1 -1
- package/dist/auth/permit_offer_queries.d.ts +68 -9
- package/dist/auth/permit_offer_queries.d.ts.map +1 -1
- package/dist/auth/permit_offer_queries.js +147 -35
- package/dist/auth/permit_offer_schema.d.ts +23 -1
- package/dist/auth/permit_offer_schema.d.ts.map +1 -1
- package/dist/auth/permit_offer_schema.js +5 -0
- package/dist/auth/permit_queries.d.ts +17 -5
- package/dist/auth/permit_queries.d.ts.map +1 -1
- package/dist/auth/permit_queries.js +19 -8
- package/dist/auth/request_context.d.ts +321 -38
- package/dist/auth/request_context.d.ts.map +1 -1
- package/dist/auth/request_context.js +393 -66
- package/dist/auth/route_guards.d.ts +10 -4
- package/dist/auth/route_guards.d.ts.map +1 -1
- package/dist/auth/route_guards.js +14 -8
- package/dist/auth/self_service_role_action_specs.d.ts +2 -0
- package/dist/auth/self_service_role_action_specs.d.ts.map +1 -1
- package/dist/auth/self_service_role_action_specs.js +2 -0
- package/dist/auth/self_service_role_actions.d.ts +6 -5
- package/dist/auth/self_service_role_actions.d.ts.map +1 -1
- package/dist/auth/self_service_role_actions.js +18 -8
- package/dist/db/migrate.d.ts +11 -7
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +9 -6
- package/dist/dev/setup.d.ts.map +1 -1
- package/dist/dev/setup.js +5 -3
- package/dist/hono_context.d.ts +77 -0
- package/dist/hono_context.d.ts.map +1 -1
- package/dist/hono_context.js +50 -0
- package/dist/http/CLAUDE.md +80 -17
- package/dist/http/error_schemas.d.ts +92 -1
- package/dist/http/error_schemas.d.ts.map +1 -1
- package/dist/http/error_schemas.js +73 -16
- package/dist/http/jsonrpc_errors.d.ts +27 -2
- package/dist/http/jsonrpc_errors.d.ts.map +1 -1
- package/dist/http/jsonrpc_errors.js +26 -2
- package/dist/http/route_spec.d.ts +62 -4
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/route_spec.js +117 -21
- package/dist/http/schema_helpers.d.ts +13 -1
- package/dist/http/schema_helpers.d.ts.map +1 -1
- package/dist/http/schema_helpers.js +21 -2
- package/dist/http/surface.d.ts +10 -1
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +2 -2
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +11 -1
- package/dist/testing/CLAUDE.md +23 -17
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +15 -13
- package/dist/testing/adversarial_headers.js +1 -1
- package/dist/testing/app_server.js +2 -2
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +21 -7
- package/dist/testing/auth_apps.d.ts.map +1 -1
- package/dist/testing/auth_apps.js +6 -3
- package/dist/testing/entities.d.ts +2 -1
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/entities.js +1 -0
- package/dist/testing/integration_helpers.d.ts +4 -2
- package/dist/testing/integration_helpers.d.ts.map +1 -1
- package/dist/testing/integration_helpers.js +9 -5
- package/dist/testing/middleware.d.ts +12 -8
- package/dist/testing/middleware.d.ts.map +1 -1
- package/dist/testing/middleware.js +67 -25
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_helpers.js +3 -1
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +5 -1
- package/dist/ui/CLAUDE.md +16 -10
- package/dist/ui/PermitOfferForm.svelte +14 -0
- package/dist/ui/PermitOfferForm.svelte.d.ts +6 -0
- package/dist/ui/PermitOfferForm.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.d.ts +8 -1
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.js +14 -3
- package/dist/ui/permit_offers_state.svelte.d.ts +9 -1
- package/dist/ui/permit_offers_state.svelte.d.ts.map +1 -1
- package/dist/ui/permit_offers_state.svelte.js +7 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"self_service_role_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/self_service_role_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"self_service_role_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/self_service_role_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,2BAA2B,CAAC;AAIzE,0FAA0F;AAC1F,eAAO,MAAM,oCAAoC,EAAG,gCAAyC,CAAC;AAE9F,yCAAyC;AACzC,eAAO,MAAM,uBAAuB;;;;kBAOlC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;;;;kBAInC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEhF,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;CAWT,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,EAAE,aAAa,CAAC,yBAAyB,CAEvF,CAAC"}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
import { RoleName } from './role_schema.js';
|
|
12
|
+
import { ActingActor } from './account_schema.js';
|
|
12
13
|
/** Error reason — caller asked to self-toggle a role outside the configured allowlist. */
|
|
13
14
|
export const ERROR_ROLE_NOT_SELF_SERVICE_ELIGIBLE = 'role_not_self_service_eligible';
|
|
14
15
|
/** Input for `self_service_role_set`. */
|
|
@@ -17,6 +18,7 @@ export const SelfServiceRoleSetInput = z.strictObject({
|
|
|
17
18
|
enabled: z.boolean().meta({
|
|
18
19
|
description: 'Desired post-call state. `true` grants if not held; `false` revokes if held. Idempotent in both directions.',
|
|
19
20
|
}),
|
|
21
|
+
acting: ActingActor,
|
|
20
22
|
});
|
|
21
23
|
/**
|
|
22
24
|
* Output for `self_service_role_set`. `enabled` echoes the post-call state
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
*/
|
|
34
34
|
import { type RpcAction } from '../actions/action_rpc.js';
|
|
35
35
|
import type { RoleSchemaResult } from './role_schema.js';
|
|
36
|
-
import type {
|
|
36
|
+
import type { AuditEmitDeps } from './deps.js';
|
|
37
37
|
/** Options for `create_self_service_role_actions`. */
|
|
38
38
|
export interface SelfServiceRoleActionsOptions {
|
|
39
39
|
/**
|
|
@@ -50,12 +50,13 @@ export interface SelfServiceRoleActionsOptions {
|
|
|
50
50
|
roles?: RoleSchemaResult;
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
|
-
* Dependencies for `create_self_service_role_actions`.
|
|
54
|
-
*
|
|
55
|
-
*
|
|
53
|
+
* Dependencies for `create_self_service_role_actions`.
|
|
54
|
+
*
|
|
55
|
+
* Aliases the shared `AuditEmitDeps` so consumers thread one deps object
|
|
56
|
+
* through every action factory. `audit_log_config` is consumed by
|
|
56
57
|
* `audit_log_fire_and_forget`.
|
|
57
58
|
*/
|
|
58
|
-
export type SelfServiceRoleActionDeps =
|
|
59
|
+
export type SelfServiceRoleActionDeps = AuditEmitDeps;
|
|
59
60
|
/**
|
|
60
61
|
* Build the unified self-service role toggle RPC action.
|
|
61
62
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"self_service_role_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/self_service_role_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"self_service_role_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/self_service_role_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAA4C,KAAK,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAEnG,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAY7C,sDAAsD;AACtD,MAAM,WAAW,6BAA6B;IAC7C;;;;OAIG;IACH,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC;;;;OAIG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,GAAG,aAAa,CAAC;AAEtD;;;;;;;GAOG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,yBAAyB,EAC/B,SAAS,6BAA6B,KACpC,KAAK,CAAC,SAAS,CA8HjB,CAAC"}
|
|
@@ -31,18 +31,13 @@
|
|
|
31
31
|
*
|
|
32
32
|
* @module
|
|
33
33
|
*/
|
|
34
|
-
import {
|
|
34
|
+
import { rpc_actor_action } from '../actions/action_rpc.js';
|
|
35
35
|
import { jsonrpc_errors } from '../http/jsonrpc_errors.js';
|
|
36
36
|
import { query_grant_permit, query_revoke_permit } from './permit_queries.js';
|
|
37
37
|
import { audit_log_fire_and_forget } from './audit_log_queries.js';
|
|
38
38
|
import { is_permit_active } from './account_schema.js';
|
|
39
39
|
import { has_scoped_role } from './request_context.js';
|
|
40
40
|
import { ERROR_ROLE_NOT_SELF_SERVICE_ELIGIBLE, self_service_role_set_action_spec, } from './self_service_role_action_specs.js';
|
|
41
|
-
const require_request_auth = (auth) => {
|
|
42
|
-
if (!auth)
|
|
43
|
-
throw new Error('unreachable: action auth guard did not enforce authentication');
|
|
44
|
-
return auth;
|
|
45
|
-
};
|
|
46
41
|
/**
|
|
47
42
|
* Build the unified self-service role toggle RPC action.
|
|
48
43
|
*
|
|
@@ -69,7 +64,7 @@ export const create_self_service_role_actions = (deps, options) => {
|
|
|
69
64
|
}
|
|
70
65
|
};
|
|
71
66
|
const handler = async (input, ctx) => {
|
|
72
|
-
const auth =
|
|
67
|
+
const auth = ctx.auth;
|
|
73
68
|
reject_if_ineligible(input.role);
|
|
74
69
|
if (input.enabled) {
|
|
75
70
|
// Pre-check for idempotent re-grant. `query_grant_permit` is itself
|
|
@@ -91,10 +86,19 @@ export const create_self_service_role_actions = (deps, options) => {
|
|
|
91
86
|
expires_at: null,
|
|
92
87
|
granted_by: auth.actor.id,
|
|
93
88
|
});
|
|
89
|
+
// `permit_grant` is the canonical actor-bound-subject event —
|
|
90
|
+
// populate both target columns even on self-service so the
|
|
91
|
+
// "always populated for permit_grant" rule holds uniformly
|
|
92
|
+
// regardless of who initiated the grant. On self-service the
|
|
93
|
+
// grantor and grantee are the same identity; admin direct-grant
|
|
94
|
+
// (separate code path) populates the same columns with the
|
|
95
|
+
// grantee actor.
|
|
94
96
|
void audit_log_fire_and_forget(ctx, {
|
|
95
97
|
event_type: 'permit_grant',
|
|
96
98
|
actor_id: auth.actor.id,
|
|
97
99
|
account_id: auth.account.id,
|
|
100
|
+
target_account_id: auth.account.id,
|
|
101
|
+
target_actor_id: auth.actor.id,
|
|
98
102
|
ip: ctx.client_ip,
|
|
99
103
|
metadata: {
|
|
100
104
|
role: permit.role,
|
|
@@ -120,10 +124,16 @@ export const create_self_service_role_actions = (deps, options) => {
|
|
|
120
124
|
// Raced with another revoker — treat as already revoked.
|
|
121
125
|
return { ok: true, enabled: false, changed: false };
|
|
122
126
|
}
|
|
127
|
+
// Same actor-bound rule as the grant branch — `permit_revoke`
|
|
128
|
+
// always populates both target columns even on self-service so
|
|
129
|
+
// forensic queries that filter on `target_actor_id IS NOT NULL`
|
|
130
|
+
// don't silently miss self-toggled permits.
|
|
123
131
|
void audit_log_fire_and_forget(ctx, {
|
|
124
132
|
event_type: 'permit_revoke',
|
|
125
133
|
actor_id: auth.actor.id,
|
|
126
134
|
account_id: auth.account.id,
|
|
135
|
+
target_account_id: auth.account.id,
|
|
136
|
+
target_actor_id: auth.actor.id,
|
|
127
137
|
ip: ctx.client_ip,
|
|
128
138
|
metadata: {
|
|
129
139
|
role: result.role,
|
|
@@ -134,5 +144,5 @@ export const create_self_service_role_actions = (deps, options) => {
|
|
|
134
144
|
}, deps);
|
|
135
145
|
return { ok: true, enabled: false, changed: true };
|
|
136
146
|
};
|
|
137
|
-
return [
|
|
147
|
+
return [rpc_actor_action(self_service_role_set_action_spec, handler)];
|
|
138
148
|
};
|
package/dist/db/migrate.d.ts
CHANGED
|
@@ -6,12 +6,15 @@
|
|
|
6
6
|
* `(namespace, name, sequence, applied_at)` — and the runner verifies the
|
|
7
7
|
* applied list is a name-prefix of the code's migration array at boot.
|
|
8
8
|
*
|
|
9
|
-
* **
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
9
|
+
* **Schema is not stabilized yet — append-only is NOT the rule.** While
|
|
10
|
+
* fuz_app is pre-stable, migration bodies, names, and positions can change
|
|
11
|
+
* freely between versions; consumers upgrading across a schema change are
|
|
12
|
+
* expected to drop and re-bootstrap their dev/test databases (production
|
|
13
|
+
* deployments are not yet a supported use case). Once the schema is
|
|
14
|
+
* declared stable a hard append-only-after-publish rule will apply and the
|
|
15
|
+
* cliff will be called out in that release's notes; until then, body edits
|
|
16
|
+
* to a published migration slip past the runner (no content hashing) by
|
|
17
|
+
* design — they're the recommended way to evolve the schema.
|
|
15
18
|
*
|
|
16
19
|
* **Chain-level transactions**: All pending migrations in a namespace run in
|
|
17
20
|
* a single transaction. Any failure rolls back every migration in that run —
|
|
@@ -53,7 +56,8 @@ export interface Migration {
|
|
|
53
56
|
/**
|
|
54
57
|
* A named group of ordered migrations.
|
|
55
58
|
*
|
|
56
|
-
* Array index = position in the chain.
|
|
59
|
+
* Array index = position in the chain. Pre-stable: bodies, names, and
|
|
60
|
+
* positions can change between versions (consumers re-bootstrap on upgrade).
|
|
57
61
|
*/
|
|
58
62
|
export interface MigrationNamespace {
|
|
59
63
|
namespace: string;
|
package/dist/db/migrate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/migrate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/migrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,SAAS,CAAC;AAEhC;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CAC7B;AAED,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAC3B,sBAAsB,GACtB,sBAAsB,GACtB,mBAAmB,GACnB,kBAAkB,GAClB,2BAA2B,GAC3B,4BAA4B,GAC5B,sCAAsC,CAAC;AAE1C,8DAA8D;AAC9D,MAAM,WAAW,qBAAqB;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;gBAEnC,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;CAQtF;AA6ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,cAAc,GAC1B,IAAI,EAAE,EACN,YAAY,KAAK,CAAC,kBAAkB,CAAC,KACnC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAuFhC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,QAAQ,GACpB,IAAI,EAAE,EACN,IAAI,kBAAkB,EACtB,OAAO,aAAa,CAAC,MAAM,CAAC,KAC1B,OAAO,CAAC,IAAI,CA+Dd,CAAC"}
|
package/dist/db/migrate.js
CHANGED
|
@@ -6,12 +6,15 @@
|
|
|
6
6
|
* `(namespace, name, sequence, applied_at)` — and the runner verifies the
|
|
7
7
|
* applied list is a name-prefix of the code's migration array at boot.
|
|
8
8
|
*
|
|
9
|
-
* **
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
9
|
+
* **Schema is not stabilized yet — append-only is NOT the rule.** While
|
|
10
|
+
* fuz_app is pre-stable, migration bodies, names, and positions can change
|
|
11
|
+
* freely between versions; consumers upgrading across a schema change are
|
|
12
|
+
* expected to drop and re-bootstrap their dev/test databases (production
|
|
13
|
+
* deployments are not yet a supported use case). Once the schema is
|
|
14
|
+
* declared stable a hard append-only-after-publish rule will apply and the
|
|
15
|
+
* cliff will be called out in that release's notes; until then, body edits
|
|
16
|
+
* to a published migration slip past the runner (no content hashing) by
|
|
17
|
+
* design — they're the recommended way to evolve the schema.
|
|
15
18
|
*
|
|
16
19
|
* **Chain-level transactions**: All pending migrations in a namespace run in
|
|
17
20
|
* a single transaction. Any failure rolls back every migration in that run —
|
package/dist/dev/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/dev/setup.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/dev/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACX,WAAW,EACX,aAAa,EACb,OAAO,EACP,UAAU,EACV,YAAY,EACZ,WAAW,EACX,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAQnD;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,2CAA2C;AAC3C,eAAO,MAAM,oBAAoB,EAAE,WAIlC,CAAC;AAEF,kCAAkC;AAClC,MAAM,WAAW,cAAc;IAC9B,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,yCAAyC;AACzC,MAAM,WAAW,gBAAgB;IAChC,kEAAkE;IAClE,OAAO,EAAE,OAAO,CAAC;IACjB,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,kCAAkC;AAClC,MAAM,WAAW,aAAa;IAC7B,+CAA+C;IAC/C,KAAK,EAAE,OAAO,CAAC;IACf,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,OAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;CACxC;AAED,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC/B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,qEAAqE;IACrE,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,GAAG,CAAC,EAAE,WAAW,CAAC;CAClB;AAED,2CAA2C;AAC3C,MAAM,WAAW,0BAA0B;IAC1C,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,GAAG,CAAC,EAAE,WAAW,CAAC;CAClB;AAED,qCAAqC;AACrC,MAAM,WAAW,qBAAqB;IACrC,GAAG,CAAC,EAAE,WAAW,CAAC;CAClB;AAED,oCAAoC;AACpC,MAAM,WAAW,oBAAoB;IACpC,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,WAAW,CAAC;CAClB;AAID;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAQpD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAAU,MAAM,WAAW,KAAG,OAAO,CAAC,MAAM,CAI3E,CAAC;AAIF;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GACxB,MAAM,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,CAAC,EACjD,UAAU,MAAM,EAChB,MAAM,MAAM,KACV,OAAO,CAAC,MAAM,GAAG,SAAS,CAU5B,CAAC;AAIF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GAC1B,MAAM,UAAU,GAAG,WAAW,GAAG,WAAW,EAC5C,UAAU,MAAM,EAChB,cAAc,MAAM,EACpB,UAAU,eAAe,KACvB,OAAO,CAAC,cAAc,CAiDxB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,GACjC,MAAM,UAAU,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,EACtD,UAAU,MAAM,EAChB,UAAU,0BAA0B,KAClC,OAAO,CAAC,gBAAgB,CA0B1B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GACjC,MAAM,UAAU,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,EACrE,UAAU,MAAM,EAChB,UAAU,0BAA0B,KAClC,OAAO,CAAC,gBAAgB,CAoB1B,CAAC;AAIF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAC3B,MAAM,WAAW,EACjB,SAAS,MAAM,EACf,UAAU,qBAAqB,KAC7B,OAAO,CAAC,aAAa,CAgBvB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,GAC1B,MAAM,WAAW,GAAG,UAAU,GAAG,YAAY,EAC7C,cAAc,MAAM,EACpB,UAAU,oBAAoB,KAC5B,OAAO,CAAC,aAAa,CA8CvB,CAAC;AAIF,mCAAmC;AACnC,MAAM,WAAW,mBAAmB;IACnC,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED,oCAAoC;AACpC,MAAM,WAAW,oBAAoB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,2CAA2C;AAC3C,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACpD,oEAAoE;IACpE,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACrD;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAC5B,MAAM,kBAAkB,EACxB,OAAO,mBAAmB,EAC1B,UAAU;IAAC,GAAG,CAAC,EAAE,WAAW,CAAA;CAAC,KAC3B,OAAO,CAAC,oBAAoB,CAwC9B,CAAC"}
|
package/dist/dev/setup.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
|
-
import { query_account_by_username,
|
|
11
|
+
import { query_account_by_username, query_actors_by_account, query_create_account_with_actor, } from '../auth/account_queries.js';
|
|
12
12
|
import { query_grant_permit } from '../auth/permit_queries.js';
|
|
13
13
|
/** Default logger using bracket format. */
|
|
14
14
|
export const default_setup_logger = {
|
|
@@ -292,11 +292,13 @@ export const seed_dev_account = async (deps, input, options) => {
|
|
|
292
292
|
const query_deps = { db: deps.db };
|
|
293
293
|
const existing = await query_account_by_username(query_deps, input.username);
|
|
294
294
|
if (existing) {
|
|
295
|
-
const
|
|
296
|
-
if (
|
|
295
|
+
const actors = await query_actors_by_account(query_deps, existing.id);
|
|
296
|
+
if (actors.length === 0) {
|
|
297
297
|
log.error(`dev account '${input.username}' exists but has no actor`);
|
|
298
298
|
throw new Error(`dev account '${input.username}' has no actor`);
|
|
299
299
|
}
|
|
300
|
+
// Dev seed is single-actor by construction; pick the first.
|
|
301
|
+
const actor = actors[0];
|
|
300
302
|
for (const role of input.roles ?? []) {
|
|
301
303
|
await query_grant_permit(query_deps, {
|
|
302
304
|
actor_id: actor.id,
|
package/dist/hono_context.d.ts
CHANGED
|
@@ -25,6 +25,63 @@ export type CredentialType = z.infer<typeof CredentialType>;
|
|
|
25
25
|
export declare const CREDENTIAL_TYPE_KEY = "credential_type";
|
|
26
26
|
/** Hono context variable name for the authenticated API token id. */
|
|
27
27
|
export declare const AUTH_API_TOKEN_ID_KEY = "auth_api_token_id";
|
|
28
|
+
/**
|
|
29
|
+
* Hono context variable name for the authenticated account id.
|
|
30
|
+
*
|
|
31
|
+
* Set by the auth middleware (session, bearer, or daemon token) on a valid
|
|
32
|
+
* credential. `null` for unauthenticated requests. The route-spec wrapper /
|
|
33
|
+
* RPC dispatcher's authorization phase reads this when resolving the acting
|
|
34
|
+
* actor; account-grain auth guards (`require_auth`) and account-grain handlers
|
|
35
|
+
* read it directly.
|
|
36
|
+
*/
|
|
37
|
+
export declare const ACCOUNT_ID_KEY = "auth_account_id";
|
|
38
|
+
/**
|
|
39
|
+
* Hono context variable name for the test-harness pre-baked context flag.
|
|
40
|
+
*
|
|
41
|
+
* Test harnesses (`create_test_app_from_specs`, `create_fake_hono_context`,
|
|
42
|
+
* the WS round-trip `connect()` helper, plus per-test middleware that
|
|
43
|
+
* pre-populates `REQUEST_CONTEXT_KEY`) set this to `true` so
|
|
44
|
+
* `apply_authorization_phase` skips its DB-backed actor resolution and
|
|
45
|
+
* trusts the supplied `RequestContext`. Production middleware never sets
|
|
46
|
+
* this key — only test code does. The flag is the explicit escape hatch
|
|
47
|
+
* that replaced the implicit "is `REQUEST_CONTEXT_KEY` already set?" probe,
|
|
48
|
+
* so that future production code consulting `REQUEST_CONTEXT_KEY` cannot
|
|
49
|
+
* silently bypass the live build.
|
|
50
|
+
*/
|
|
51
|
+
export declare const TEST_CONTEXT_PRESET_KEY = "test_context_preset";
|
|
52
|
+
/**
|
|
53
|
+
* Cached parsed JSON request body, keyed by `'cached_request_body'`.
|
|
54
|
+
*
|
|
55
|
+
* Written by `read_raw_acting` (in the dispatcher's authorization
|
|
56
|
+
* phase) when it pre-parses the body to extract the `acting` field;
|
|
57
|
+
* read by `create_input_validation` so the input-validation step does
|
|
58
|
+
* not pay for a second `JSON.parse` on the same Hono-cached body text.
|
|
59
|
+
*
|
|
60
|
+
* Decouples our pipeline from Hono's internal `bodyCache` shape: Hono
|
|
61
|
+
* caches the body *text* (so a second `c.req.json()` call doesn't
|
|
62
|
+
* re-read the request stream), but each call still re-runs
|
|
63
|
+
* `JSON.parse(text)`. Storing the parsed value here saves the second
|
|
64
|
+
* parse and keeps fuz_app from depending on undocumented Hono
|
|
65
|
+
* implementation details.
|
|
66
|
+
*
|
|
67
|
+
* Three states:
|
|
68
|
+
*
|
|
69
|
+
* - Key absent — body has not been pre-parsed yet (the route had no
|
|
70
|
+
* `acting` to extract, or the request is GET).
|
|
71
|
+
* - `{ok: true, body: unknown}` — pre-parse succeeded; the parsed
|
|
72
|
+
* value (object, primitive, or array) is in `body`.
|
|
73
|
+
* - `{ok: false}` — pre-parse threw (malformed JSON). The downstream
|
|
74
|
+
* input-validation step short-circuits with `ERROR_INVALID_JSON_BODY`
|
|
75
|
+
* instead of re-parsing.
|
|
76
|
+
*/
|
|
77
|
+
export declare const CACHED_REQUEST_BODY_KEY = "cached_request_body";
|
|
78
|
+
/** The shape stored under `CACHED_REQUEST_BODY_KEY`. */
|
|
79
|
+
export type CachedRequestBody = {
|
|
80
|
+
ok: true;
|
|
81
|
+
body: unknown;
|
|
82
|
+
} | {
|
|
83
|
+
ok: false;
|
|
84
|
+
};
|
|
28
85
|
declare module 'hono' {
|
|
29
86
|
interface ContextVariableMap {
|
|
30
87
|
/** Resolved client IP, set by the trusted proxy middleware. */
|
|
@@ -36,6 +93,13 @@ declare module 'hono' {
|
|
|
36
93
|
validated_query: unknown;
|
|
37
94
|
/** How the request was authenticated (`'session'`, `'api_token'`, or `'daemon_token'`). */
|
|
38
95
|
credential_type: CredentialType | null;
|
|
96
|
+
/**
|
|
97
|
+
* Authenticated account id. Set by the session / bearer / daemon-token
|
|
98
|
+
* middleware on a valid credential; `null` for unauthenticated requests.
|
|
99
|
+
* The dispatcher's authorization phase resolves the acting actor against
|
|
100
|
+
* this id; `require_auth` 401s when it is `null`.
|
|
101
|
+
*/
|
|
102
|
+
auth_account_id: string | null;
|
|
39
103
|
/**
|
|
40
104
|
* blake3 hash of the authenticated session token, or `null` for non-session
|
|
41
105
|
* credentials. Set by `create_request_context_middleware`. Used to scope
|
|
@@ -57,6 +121,19 @@ declare module 'hono' {
|
|
|
57
121
|
* all effects are awaited before the response returns.
|
|
58
122
|
*/
|
|
59
123
|
pending_effects: Array<Promise<void>>;
|
|
124
|
+
/**
|
|
125
|
+
* Set to `true` by test harnesses that pre-populate `request_context`
|
|
126
|
+
* to bypass the dispatcher's DB-backed actor resolution. Read by
|
|
127
|
+
* `apply_authorization_phase`. Production middleware never sets this.
|
|
128
|
+
*/
|
|
129
|
+
test_context_preset: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Pre-parsed JSON request body cache. Written by `read_raw_acting`
|
|
132
|
+
* (the dispatcher's `acting` extractor) and read by
|
|
133
|
+
* `create_input_validation` so the same body is not parsed twice.
|
|
134
|
+
* See `CACHED_REQUEST_BODY_KEY` for state semantics.
|
|
135
|
+
*/
|
|
136
|
+
cached_request_body: CachedRequestBody;
|
|
60
137
|
}
|
|
61
138
|
}
|
|
62
139
|
//# sourceMappingURL=hono_context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hono_context.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/hono_context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAE9D,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,mDAAoD,CAAC;AAElF,yDAAyD;AACzD,eAAO,MAAM,cAAc;;;;EAA2B,CAAC;AACvD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,0DAA0D;AAC1D,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAErD,qEAAqE;AACrE,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AAEzD,OAAO,QAAQ,MAAM,CAAC;IACrB,UAAU,kBAAkB;QAC3B,+DAA+D;QAC/D,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,eAAe,EAAE,cAAc,GAAG,IAAI,CAAC;QACvC,eAAe,EAAE,OAAO,CAAC;QACzB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,eAAe,EAAE,OAAO,CAAC;QACzB,2FAA2F;QAC3F,eAAe,EAAE,cAAc,GAAG,IAAI,CAAC;QACvC;;;;;WAKG;QACH,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;QACvC;;;;;;WAMG;QACH,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC;;;;WAIG;QACH,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"hono_context.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/hono_context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAE9D,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,mDAAoD,CAAC;AAElF,yDAAyD;AACzD,eAAO,MAAM,cAAc;;;;EAA2B,CAAC;AACvD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,0DAA0D;AAC1D,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAErD,qEAAqE;AACrE,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AAEzD;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAE7D,wDAAwD;AACxD,MAAM,MAAM,iBAAiB,GAAG;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAC,GAAG;IAAC,EAAE,EAAE,KAAK,CAAA;CAAC,CAAC;AAExE,OAAO,QAAQ,MAAM,CAAC;IACrB,UAAU,kBAAkB;QAC3B,+DAA+D;QAC/D,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,eAAe,EAAE,cAAc,GAAG,IAAI,CAAC;QACvC,eAAe,EAAE,OAAO,CAAC;QACzB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,eAAe,EAAE,OAAO,CAAC;QACzB,2FAA2F;QAC3F,eAAe,EAAE,cAAc,GAAG,IAAI,CAAC;QACvC;;;;;WAKG;QACH,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B;;;;;WAKG;QACH,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;QACvC;;;;;;WAMG;QACH,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC;;;;WAIG;QACH,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC;;;;WAIG;QACH,mBAAmB,EAAE,OAAO,CAAC;QAC7B;;;;;WAKG;QACH,mBAAmB,EAAE,iBAAiB,CAAC;KACvC;CACD"}
|
package/dist/hono_context.js
CHANGED
|
@@ -19,3 +19,53 @@ export const CredentialType = z.enum(CREDENTIAL_TYPES);
|
|
|
19
19
|
export const CREDENTIAL_TYPE_KEY = 'credential_type';
|
|
20
20
|
/** Hono context variable name for the authenticated API token id. */
|
|
21
21
|
export const AUTH_API_TOKEN_ID_KEY = 'auth_api_token_id';
|
|
22
|
+
/**
|
|
23
|
+
* Hono context variable name for the authenticated account id.
|
|
24
|
+
*
|
|
25
|
+
* Set by the auth middleware (session, bearer, or daemon token) on a valid
|
|
26
|
+
* credential. `null` for unauthenticated requests. The route-spec wrapper /
|
|
27
|
+
* RPC dispatcher's authorization phase reads this when resolving the acting
|
|
28
|
+
* actor; account-grain auth guards (`require_auth`) and account-grain handlers
|
|
29
|
+
* read it directly.
|
|
30
|
+
*/
|
|
31
|
+
export const ACCOUNT_ID_KEY = 'auth_account_id';
|
|
32
|
+
/**
|
|
33
|
+
* Hono context variable name for the test-harness pre-baked context flag.
|
|
34
|
+
*
|
|
35
|
+
* Test harnesses (`create_test_app_from_specs`, `create_fake_hono_context`,
|
|
36
|
+
* the WS round-trip `connect()` helper, plus per-test middleware that
|
|
37
|
+
* pre-populates `REQUEST_CONTEXT_KEY`) set this to `true` so
|
|
38
|
+
* `apply_authorization_phase` skips its DB-backed actor resolution and
|
|
39
|
+
* trusts the supplied `RequestContext`. Production middleware never sets
|
|
40
|
+
* this key — only test code does. The flag is the explicit escape hatch
|
|
41
|
+
* that replaced the implicit "is `REQUEST_CONTEXT_KEY` already set?" probe,
|
|
42
|
+
* so that future production code consulting `REQUEST_CONTEXT_KEY` cannot
|
|
43
|
+
* silently bypass the live build.
|
|
44
|
+
*/
|
|
45
|
+
export const TEST_CONTEXT_PRESET_KEY = 'test_context_preset';
|
|
46
|
+
/**
|
|
47
|
+
* Cached parsed JSON request body, keyed by `'cached_request_body'`.
|
|
48
|
+
*
|
|
49
|
+
* Written by `read_raw_acting` (in the dispatcher's authorization
|
|
50
|
+
* phase) when it pre-parses the body to extract the `acting` field;
|
|
51
|
+
* read by `create_input_validation` so the input-validation step does
|
|
52
|
+
* not pay for a second `JSON.parse` on the same Hono-cached body text.
|
|
53
|
+
*
|
|
54
|
+
* Decouples our pipeline from Hono's internal `bodyCache` shape: Hono
|
|
55
|
+
* caches the body *text* (so a second `c.req.json()` call doesn't
|
|
56
|
+
* re-read the request stream), but each call still re-runs
|
|
57
|
+
* `JSON.parse(text)`. Storing the parsed value here saves the second
|
|
58
|
+
* parse and keeps fuz_app from depending on undocumented Hono
|
|
59
|
+
* implementation details.
|
|
60
|
+
*
|
|
61
|
+
* Three states:
|
|
62
|
+
*
|
|
63
|
+
* - Key absent — body has not been pre-parsed yet (the route had no
|
|
64
|
+
* `acting` to extract, or the request is GET).
|
|
65
|
+
* - `{ok: true, body: unknown}` — pre-parse succeeded; the parsed
|
|
66
|
+
* value (object, primitive, or array) is in `body`.
|
|
67
|
+
* - `{ok: false}` — pre-parse threw (malformed JSON). The downstream
|
|
68
|
+
* input-validation step short-circuits with `ERROR_INVALID_JSON_BODY`
|
|
69
|
+
* instead of re-parsing.
|
|
70
|
+
*/
|
|
71
|
+
export const CACHED_REQUEST_BODY_KEY = 'cached_request_body';
|
package/dist/http/CLAUDE.md
CHANGED
|
@@ -91,21 +91,66 @@ wrapper). See `../auth/signup_routes.ts`.
|
|
|
91
91
|
|
|
92
92
|
`apply_route_specs` assembles the following middleware chain per spec:
|
|
93
93
|
|
|
94
|
-
1. **
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
94
|
+
1. **Params validation** — `spec.params` → `validated_params` context
|
|
95
|
+
var; mismatch returns 400 `ERROR_INVALID_ROUTE_PARAMS` with Zod
|
|
96
|
+
`issues`
|
|
97
|
+
2. **Query validation** — `spec.query` → `validated_query`; mismatch
|
|
98
|
+
returns 400 `ERROR_INVALID_QUERY_PARAMS`
|
|
99
|
+
3. **Pre-validation auth guards** — `require_auth` (401
|
|
100
|
+
`ERROR_AUTHENTICATION_REQUIRED`) for any non-public route. Fires
|
|
101
|
+
before any body parsing so unauthenticated callers never see
|
|
102
|
+
route-shape information from input parse failures. The
|
|
103
|
+
`AuthGuardResolver` (e.g. `fuz_auth_guard_resolver` from
|
|
104
|
+
`../auth/route_guards.ts`) returns this set as
|
|
105
|
+
`pre_validation: Array<MiddlewareHandler>`.
|
|
106
|
+
4. **Authorization phase** — when the route's input schema declares
|
|
107
|
+
`acting?: ActingActor` or `spec.auth.type` is `'role'` / `'keeper'`,
|
|
108
|
+
resolves the acting actor against `c.var.account_id` (set by the
|
|
109
|
+
auth middleware) plus the raw `acting` value extracted from query
|
|
110
|
+
(GET) or pre-parsed JSON body (mutating methods), builds
|
|
111
|
+
`RequestContext` via `build_request_context`, and sets
|
|
112
|
+
`REQUEST_CONTEXT_KEY`. Resolution failures return 400
|
|
113
|
+
`ERROR_ACTOR_REQUIRED` (with `available[]`) or
|
|
114
|
+
`ERROR_ACTOR_NOT_ON_ACCOUNT` (or 500 `ERROR_NO_ACTORS_ON_ACCOUNT`
|
|
115
|
+
when the actor enumeration came back empty, 500 `ERROR_ACCOUNT_VANISHED`
|
|
116
|
+
on torn account/actor reads after a successful resolve) before the
|
|
117
|
+
handler runs. Account-grain
|
|
118
|
+
routes skip this phase; their handlers see no `RequestContext` (or
|
|
119
|
+
one with `actor: null`, depending on the helper). The pre-parsed body
|
|
120
|
+
lands on `c.var.cached_request_body` (see step 6) so the subsequent
|
|
121
|
+
input-validation step reads from there instead of re-parsing.
|
|
122
|
+
5. **Post-authorization auth guards** — `require_role(role)` /
|
|
123
|
+
`require_keeper` (403 `ERROR_INSUFFICIENT_PERMISSIONS` /
|
|
124
|
+
`ERROR_KEEPER_REQUIRES_DAEMON_TOKEN`). Reads `REQUEST_CONTEXT_KEY`
|
|
125
|
+
populated by step 4. The resolver returns this set as
|
|
126
|
+
`post_authorization: Array<MiddlewareHandler>`.
|
|
127
|
+
6. **Input validation** — JSON body parsed + validated; mismatch returns
|
|
128
|
+
400 `ERROR_INVALID_JSON_BODY` (not JSON) or `ERROR_INVALID_REQUEST_BODY`
|
|
129
|
+
(schema failure with `issues`). Skipped on GET and `z.null()` inputs.
|
|
130
|
+
On mutating methods, the parse result is shared with the authorization
|
|
131
|
+
phase's pre-parse via `c.var.cached_request_body`
|
|
132
|
+
(`CACHED_REQUEST_BODY_KEY` from `hono_context.ts`) — the cache is
|
|
133
|
+
fuz_app-owned, not Hono's internal `bodyCache`, so a future Hono
|
|
134
|
+
internals refactor can't break our second-parse-avoidance contract.
|
|
135
|
+
7. **Handler** — wrapped in transaction when `use_transaction` (see
|
|
136
|
+
above), receives `RouteContext`
|
|
137
|
+
8. **DEV-only output + error validation** — wraps the handler (see below)
|
|
138
|
+
9. **Error catch** — catches `ThrownJsonrpcError` → maps to HTTP status +
|
|
139
|
+
the flat REST `ApiError` body (`{error: <reason>, message?, ...rest_data}`);
|
|
140
|
+
catches generic `Error` → 500 `{error: 'internal_error', message?}`
|
|
141
|
+
(message only included in DEV). The reason string comes from
|
|
142
|
+
`err.data.reason` when set (consumer-supplied canonical reason
|
|
143
|
+
override) or from `jsonrpc_error_code_to_name(err.code)` (e.g.
|
|
144
|
+
`-32003 → 'not_found'`). The flat shape matches what middleware
|
|
145
|
+
and direct handlers emit (`c.json({error: ERROR_FOO}, status)`,
|
|
146
|
+
`c.json(failure.body, status)` from the dispatcher's authorization
|
|
147
|
+
phase) — REST callers see one envelope across every emit site, while
|
|
148
|
+
the JSON-RPC dispatcher keeps its own `{jsonrpc, id, error: {code,
|
|
149
|
+
message, data}}` envelope on the RPC mount
|
|
150
|
+
|
|
151
|
+
The auth-before-validation order matches the RPC dispatcher
|
|
152
|
+
(`actions/action_rpc.ts`) so HTTP RPC and REST surface failures with
|
|
153
|
+
the same priority: 401 → 403 → 400 → handler.
|
|
109
154
|
|
|
110
155
|
Duplicate `method path` pairs throw at registration.
|
|
111
156
|
|
|
@@ -162,21 +207,39 @@ Pair every schema with the `z.infer` type export (`export type ApiError = z.infe
|
|
|
162
207
|
|
|
163
208
|
### Three-layer error-schema merge
|
|
164
209
|
|
|
165
|
-
`merge_error_schemas(spec, middleware_errors?)` (in `schema_helpers.ts`)
|
|
210
|
+
`merge_error_schemas(spec, middleware_errors?, acting_aware?)` (in `schema_helpers.ts`)
|
|
166
211
|
merges three layers, later overrides earlier at the same status code:
|
|
167
212
|
|
|
168
|
-
1. **Derived** — from `derive_error_schemas(auth, has_input
|
|
213
|
+
1. **Derived** — from `derive_error_schemas({auth, has_input?, has_params?, has_query?, rate_limit?, acting_aware?})`:
|
|
169
214
|
- `has_input || has_params || has_query` → 400 `ValidationError`
|
|
170
215
|
- `auth.type === 'authenticated'` → 401 `ApiError`
|
|
171
216
|
- `auth.type === 'role'` → 401 `ApiError` + 403 `PermissionError`
|
|
172
217
|
- `auth.type === 'keeper'` → 401 `ApiError` + 403 `KeeperError`
|
|
173
218
|
- `rate_limit` → 429 `RateLimitError`
|
|
219
|
+
- `acting_aware` → widens 400 to a union with `ActorRequiredError` /
|
|
220
|
+
`ActorNotOnAccountError` and adds 500 union of `NoActorsOnAccountError`
|
|
221
|
+
/ `AccountVanishedError`. Mirrors what the dispatcher's authorization
|
|
222
|
+
phase actually emits on routes whose input declares `acting?: ActingActor`
|
|
223
|
+
or whose auth requires permits — so DEV-mode error-schema validation in
|
|
224
|
+
`wrap_output_validation` doesn't reject the auth phase's body.
|
|
174
225
|
2. **Middleware** — from `MiddlewareSpec.errors` that apply to the route's
|
|
175
226
|
path (via `middleware_applies`)
|
|
176
227
|
3. **Explicit** — `RouteSpec.errors` — always wins
|
|
177
228
|
|
|
178
229
|
Routes typically only need `errors` for handler-specific codes (404, 409, 422).
|
|
179
230
|
|
|
231
|
+
`acting_aware` is computed at the call site (`apply_route_specs` /
|
|
232
|
+
`generate_app_surface`) via the optional `is_acting_aware?: (spec) => boolean`
|
|
233
|
+
callback. Computation lives in the consumer because the canonical
|
|
234
|
+
"input declares `acting?: ActingActor`" check uses reference equality with
|
|
235
|
+
the canonical `ActingActor` Zod schema in `auth/account_schema.ts`, and
|
|
236
|
+
`http/` stays auth-agnostic. fuz_app's `create_app_server` wires
|
|
237
|
+
`(spec) => is_actor_implying_auth(spec.auth) || input_schema_declares_acting(spec.input)`
|
|
238
|
+
— consumers building on raw `apply_route_specs` opt in by passing the
|
|
239
|
+
same predicate (or a narrower one). When the callback is omitted the
|
|
240
|
+
flag defaults to false so frameworks not using fuz_app's auth phase don't
|
|
241
|
+
get fuz_app-specific shapes on their derived surface.
|
|
242
|
+
|
|
180
243
|
### `ERROR_*` constants by category
|
|
181
244
|
|
|
182
245
|
- **Validation**: `ERROR_INVALID_REQUEST_BODY`, `ERROR_INVALID_JSON_BODY`,
|