@sixb/core 0.1.5 → 0.1.7
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/index.js +37 -33
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/types/definitions.d.ts +8 -2
- package/dist/actions/types/definitions.d.ts.map +1 -1
- package/dist/actions/worker.js +3 -3
- package/dist/agents/adapters.d.ts +33 -76
- package/dist/agents/adapters.d.ts.map +1 -1
- package/dist/agents/authority.d.ts +22 -6
- package/dist/agents/authority.d.ts.map +1 -1
- package/dist/agents/builders.d.ts +3 -11
- package/dist/agents/builders.d.ts.map +1 -1
- package/dist/agents/context.js +2 -2
- package/dist/agents/dispatch.d.ts +9 -1
- package/dist/agents/dispatch.d.ts.map +1 -1
- package/dist/agents/errors.d.ts +2 -2
- package/dist/agents/errors.d.ts.map +1 -1
- package/dist/agents/execution.d.ts +9 -10
- package/dist/agents/execution.d.ts.map +1 -1
- package/dist/agents/ids.d.ts +4 -0
- package/dist/agents/ids.d.ts.map +1 -1
- package/dist/agents/index.d.ts +13 -9
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +80 -68
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/message.d.ts +17 -10
- package/dist/agents/message.d.ts.map +1 -1
- package/dist/agents/model-loop.d.ts +56 -0
- package/dist/agents/model-loop.d.ts.map +1 -0
- package/dist/agents/reference.d.ts +4 -0
- package/dist/agents/reference.d.ts.map +1 -0
- package/dist/agents/request.d.ts +10 -8
- package/dist/agents/request.d.ts.map +1 -1
- package/dist/agents/retired-config.d.ts +4 -0
- package/dist/agents/retired-config.d.ts.map +1 -0
- package/dist/agents/streams.d.ts +13 -8
- package/dist/agents/streams.d.ts.map +1 -1
- package/dist/agents/streams.js +7 -5
- package/dist/agents/streams.js.map +1 -1
- package/dist/agents/tool-catalog.d.ts +9 -0
- package/dist/agents/tool-catalog.d.ts.map +1 -0
- package/dist/agents/tool-definition.d.ts +1 -0
- package/dist/agents/tool-definition.d.ts.map +1 -1
- package/dist/agents/types.d.ts +31 -68
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/agents/validation.d.ts +4 -10
- package/dist/agents/validation.d.ts.map +1 -1
- package/dist/ai-usage/execution.d.ts +53 -0
- package/dist/ai-usage/execution.d.ts.map +1 -0
- package/dist/ai-usage/index.d.ts +3 -0
- package/dist/ai-usage/index.d.ts.map +1 -0
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +7 -7
- package/dist/auth/runtime.d.ts.map +1 -1
- package/dist/auth/strategy.d.ts +1 -1
- package/dist/auth/strategy.d.ts.map +1 -1
- package/dist/auth/types.d.ts +13 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/authorization/decision.d.ts +5 -2
- package/dist/authorization/decision.d.ts.map +1 -1
- package/dist/authorization/grant-kinds.d.ts +24 -8
- package/dist/authorization/grant-kinds.d.ts.map +1 -1
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.d.ts.map +1 -1
- package/dist/authorization/index.js +8 -6
- package/dist/authorization/index.js.map +1 -1
- package/dist/authorization/resolve.d.ts +3 -3
- package/dist/authorization/resolve.d.ts.map +1 -1
- package/dist/authorization/types.d.ts +7 -5
- package/dist/authorization/types.d.ts.map +1 -1
- package/dist/blob-storage/browser.js +2 -2
- package/dist/blob-storage/index.js +3 -3
- package/dist/bootstrap/discovery.d.ts +1 -7
- package/dist/bootstrap/discovery.d.ts.map +1 -1
- package/dist/bootstrap/index.js +52 -48
- package/dist/bootstrap/index.js.map +1 -1
- package/dist/broker/index.js +2 -2
- package/dist/{chunk-zqysyfjt.js → chunk-08m3b6w8.js} +1 -1
- package/dist/{chunk-xdf9yswn.js → chunk-08twe8m6.js} +93 -8
- package/dist/chunk-08twe8m6.js.map +12 -0
- package/dist/{chunk-xkthy56g.js → chunk-1kamz6j0.js} +1 -1
- package/dist/{chunk-h6h91mfy.js → chunk-2b5qtban.js} +12 -12
- package/dist/{chunk-h6h91mfy.js.map → chunk-2b5qtban.js.map} +3 -3
- package/dist/{chunk-0172wgm9.js → chunk-2xns679x.js} +10 -2
- package/dist/{chunk-0172wgm9.js.map → chunk-2xns679x.js.map} +3 -3
- package/dist/{chunk-f83ka50g.js → chunk-37wk412q.js} +86 -28
- package/dist/{chunk-f83ka50g.js.map → chunk-37wk412q.js.map} +8 -8
- package/dist/{chunk-6d5xdj1q.js → chunk-3fqt22c4.js} +4 -4
- package/dist/{chunk-t9xghkva.js → chunk-3kv70xwp.js} +3 -2
- package/dist/{chunk-t9xghkva.js.map → chunk-3kv70xwp.js.map} +3 -3
- package/dist/{chunk-z3zp0bj1.js → chunk-407j3msh.js} +1 -1
- package/dist/{chunk-rhrbz7d4.js → chunk-4a849fr1.js} +1 -1
- package/dist/{chunk-62c7t4jc.js → chunk-4nxeacx7.js} +1 -1
- package/dist/{chunk-cy0n5dms.js → chunk-5jcdmjam.js} +1 -1
- package/dist/{chunk-819wnjz8.js → chunk-64sr682n.js} +7 -7
- package/dist/{chunk-v0egge8b.js → chunk-6ed5bwnd.js} +666 -81
- package/dist/chunk-6ed5bwnd.js.map +57 -0
- package/dist/{chunk-x2yw73hy.js → chunk-7ds9620f.js} +1 -1
- package/dist/{chunk-dm72y8wt.js → chunk-7y0f6rf1.js} +29 -16
- package/dist/chunk-7y0f6rf1.js.map +10 -0
- package/dist/{chunk-72q2y8hn.js → chunk-8tsf6dmc.js} +2 -2
- package/dist/{chunk-72q2y8hn.js.map → chunk-8tsf6dmc.js.map} +3 -3
- package/dist/{chunk-tbv03sx2.js → chunk-9aehf39w.js} +7 -7
- package/dist/{chunk-ezake7g1.js → chunk-agsvg9ar.js} +1 -1
- package/dist/{chunk-rdeagz6b.js → chunk-atmkaf60.js} +1 -1
- package/dist/{chunk-rdeagz6b.js.map → chunk-atmkaf60.js.map} +2 -2
- package/dist/chunk-c15dr03f.js +43 -0
- package/dist/chunk-c15dr03f.js.map +10 -0
- package/dist/{chunk-78c6xvyr.js → chunk-d2ndstdf.js} +8 -6
- package/dist/{chunk-78c6xvyr.js.map → chunk-d2ndstdf.js.map} +2 -2
- package/dist/{chunk-rnshztfq.js → chunk-d63tybny.js} +2 -2
- package/dist/{chunk-t0jjkep3.js → chunk-d8qkxt2v.js} +4 -2
- package/dist/chunk-d8qkxt2v.js.map +10 -0
- package/dist/{chunk-vybf6pkp.js → chunk-dbc80ad7.js} +1 -1
- package/dist/{chunk-4gz41why.js → chunk-dqn23610.js} +1 -1
- package/dist/{chunk-z3ga9q5m.js → chunk-e4rvtvpw.js} +13 -11
- package/dist/{chunk-z3ga9q5m.js.map → chunk-e4rvtvpw.js.map} +2 -2
- package/dist/{chunk-h9kxd41f.js → chunk-gbrpsx4m.js} +19 -6
- package/dist/chunk-gbrpsx4m.js.map +11 -0
- package/dist/{chunk-84h6qhmp.js → chunk-h0knpbz5.js} +468 -1236
- package/dist/chunk-h0knpbz5.js.map +38 -0
- package/dist/{chunk-zp2v2rv6.js → chunk-ha58tjtt.js} +6 -6
- package/dist/{chunk-f6erf2vv.js → chunk-hdz94br2.js} +2 -2
- package/dist/chunk-jecn6t54.js +307 -0
- package/dist/chunk-jecn6t54.js.map +12 -0
- package/dist/{chunk-dsrkgtnh.js → chunk-jq43kdvk.js} +1 -1
- package/dist/{chunk-wtmzkcht.js → chunk-k34z5rvh.js} +1 -1
- package/dist/{chunk-htq0qh7z.js → chunk-ka3a2ft3.js} +2 -2
- package/dist/{chunk-4h947jd8.js → chunk-kt81c11h.js} +2 -2
- package/dist/chunk-n2arzn6e.js +1745 -0
- package/dist/chunk-n2arzn6e.js.map +20 -0
- package/dist/{chunk-f2rt4vkh.js → chunk-n2w475r0.js} +3 -3
- package/dist/{chunk-t8t39h7v.js → chunk-n6jxh8sw.js} +10 -2
- package/dist/chunk-n6jxh8sw.js.map +10 -0
- package/dist/{chunk-drjqm1aa.js → chunk-p03r0h5s.js} +310 -28
- package/dist/chunk-p03r0h5s.js.map +16 -0
- package/dist/chunk-p2vqaxkc.js +528 -0
- package/dist/chunk-p2vqaxkc.js.map +15 -0
- package/dist/{chunk-gadsm794.js → chunk-qjycjdj6.js} +84 -11
- package/dist/chunk-qjycjdj6.js.map +12 -0
- package/dist/chunk-qjzp9xyb.js +286 -0
- package/dist/chunk-qjzp9xyb.js.map +12 -0
- package/dist/{chunk-am6eczah.js → chunk-qv38twt8.js} +50 -69
- package/dist/{chunk-am6eczah.js.map → chunk-qv38twt8.js.map} +8 -8
- package/dist/{chunk-bhxaq2nn.js → chunk-qw9gvjv5.js} +1 -1
- package/dist/{chunk-r0rry8dn.js → chunk-rp1mvzb4.js} +6 -6
- package/dist/{chunk-tkdscva6.js → chunk-rre42skh.js} +187 -18
- package/dist/chunk-rre42skh.js.map +39 -0
- package/dist/{chunk-ghteq96b.js → chunk-s5y30bc9.js} +2 -2
- package/dist/{chunk-a31h57d5.js → chunk-tn7xcs2n.js} +2 -2
- package/dist/{chunk-6gjqgd3d.js → chunk-tpnd31c1.js} +2 -1
- package/dist/chunk-tpnd31c1.js.map +11 -0
- package/dist/chunk-trxxmgnf.js +68 -0
- package/dist/chunk-trxxmgnf.js.map +11 -0
- package/dist/{chunk-ea73pzk7.js → chunk-vjjv9mrb.js} +2 -2
- package/dist/{chunk-8b55ygje.js → chunk-w3e09qqk.js} +1 -1
- package/dist/{chunk-ckxfnx7f.js → chunk-wjgm6jjt.js} +2 -2
- package/dist/{chunk-3j7573mj.js → chunk-x0qhkqje.js} +2 -2
- package/dist/{chunk-dysw7nsm.js → chunk-xdpwpkha.js} +2 -2
- package/dist/{chunk-1q02e95s.js → chunk-y35ma3mj.js} +11 -16
- package/dist/{chunk-1q02e95s.js.map → chunk-y35ma3mj.js.map} +3 -4
- package/dist/{chunk-qewtks41.js → chunk-z2sery1b.js} +64 -1
- package/dist/{chunk-qewtks41.js.map → chunk-z2sery1b.js.map} +3 -3
- package/dist/error-reporting/internal.js +4 -4
- package/dist/error-reporting/types.d.ts +7 -2
- package/dist/error-reporting/types.d.ts.map +1 -1
- package/dist/errors/catalog.d.ts +8 -0
- package/dist/errors/catalog.d.ts.map +1 -1
- package/dist/errors/internal.js +2 -2
- package/dist/events/index.js +4 -4
- package/dist/execution/agent.d.ts +18 -9
- package/dist/execution/agent.d.ts.map +1 -1
- package/dist/execution/agent.js +52 -43
- package/dist/execution/agent.js.map +1 -1
- package/dist/execution/authorization.d.ts +14 -4
- package/dist/execution/authorization.d.ts.map +1 -1
- package/dist/execution/primitive.js +45 -43
- package/dist/execution/primitive.js.map +2 -2
- package/dist/execution/request.d.ts +3 -1
- package/dist/execution/request.d.ts.map +1 -1
- package/dist/execution/request.js +46 -44
- package/dist/execution/request.js.map +3 -3
- package/dist/execution/types.d.ts +1 -1
- package/dist/execution/types.d.ts.map +1 -1
- package/dist/http/api-routes.d.ts.map +1 -1
- package/dist/http/index.js +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -77
- package/dist/index.js.map +1 -1
- package/dist/json.d.ts +2 -0
- package/dist/json.d.ts.map +1 -1
- package/dist/lake-storage/index.js +5 -5
- package/dist/logging/index.js +3 -3
- package/dist/logging/types.js +2 -2
- package/dist/materialization/index.js +2 -2
- package/dist/materializer/index.js +33 -29
- package/dist/materializer/index.js.map +1 -1
- package/dist/models/catalog.d.ts +40 -0
- package/dist/models/catalog.d.ts.map +1 -0
- package/dist/models/definitions.d.ts +25 -0
- package/dist/models/definitions.d.ts.map +1 -0
- package/dist/models/errors.d.ts +52 -0
- package/dist/models/errors.d.ts.map +1 -0
- package/dist/models/events.d.ts +192 -0
- package/dist/models/events.d.ts.map +1 -0
- package/dist/models/index.d.ts +17 -39
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +50 -0
- package/dist/models/index.js.map +9 -0
- package/dist/models/language-model.d.ts +90 -0
- package/dist/models/language-model.d.ts.map +1 -0
- package/dist/models/messages.d.ts +74 -0
- package/dist/models/messages.d.ts.map +1 -0
- package/dist/models/pricing.d.ts +69 -0
- package/dist/models/pricing.d.ts.map +1 -0
- package/dist/models/rate-card.d.ts +24 -0
- package/dist/models/rate-card.d.ts.map +1 -0
- package/dist/models/tools.d.ts +24 -0
- package/dist/models/tools.d.ts.map +1 -0
- package/dist/objects/index.js +38 -34
- package/dist/objects/index.js.map +1 -1
- package/dist/objects/query/index.js +32 -28
- package/dist/objects/query/index.js.map +1 -1
- package/dist/ontology/index.js +5 -5
- package/dist/ontology/internal.js +4 -4
- package/dist/pipelines/index.js +37 -35
- package/dist/pipelines/index.js.map +1 -1
- package/dist/projections/internal.js +35 -31
- package/dist/projections/internal.js.map +1 -1
- package/dist/queues/in-memory.d.ts +3 -2
- package/dist/queues/in-memory.d.ts.map +1 -1
- package/dist/queues/index.d.ts +3 -1
- package/dist/queues/index.d.ts.map +1 -1
- package/dist/queues/index.js +1 -1
- package/dist/queues/types.d.ts +15 -3
- package/dist/queues/types.d.ts.map +1 -1
- package/dist/runtime/create.d.ts +4 -4
- package/dist/runtime/create.d.ts.map +1 -1
- package/dist/runtime/definitions.d.ts +2 -2
- package/dist/runtime/definitions.d.ts.map +1 -1
- package/dist/runtime/host.d.ts +3 -2
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/resolve-definitions.d.ts +2 -2
- package/dist/runtime/resolve-definitions.d.ts.map +1 -1
- package/dist/runtime/sixb.d.ts +4 -2
- package/dist/runtime/sixb.d.ts.map +1 -1
- package/dist/security/every.d.ts +1 -4
- package/dist/security/every.d.ts.map +1 -1
- package/dist/security/grants.d.ts +6 -5
- package/dist/security/grants.d.ts.map +1 -1
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/registry.d.ts +1 -1
- package/dist/security/registry.d.ts.map +1 -1
- package/dist/security/types.d.ts +13 -5
- package/dist/security/types.d.ts.map +1 -1
- package/dist/security/validation.d.ts +4 -2
- package/dist/security/validation.d.ts.map +1 -1
- package/dist/storage/action-runs/failure.js +3 -3
- package/dist/storage/action-runs/provider.js +2 -2
- package/dist/storage/agents/errors.d.ts +1 -1
- package/dist/storage/agents/errors.d.ts.map +1 -1
- package/dist/storage/agents/in-memory.d.ts +3 -2
- package/dist/storage/agents/in-memory.d.ts.map +1 -1
- package/dist/storage/agents/index.d.ts +1 -1
- package/dist/storage/agents/index.d.ts.map +1 -1
- package/dist/storage/agents/provider.d.ts +11 -4
- package/dist/storage/agents/provider.d.ts.map +1 -1
- package/dist/storage/agents/provider.js +18 -15
- package/dist/storage/agents/provider.js.map +1 -1
- package/dist/storage/agents/types.d.ts +65 -17
- package/dist/storage/agents/types.d.ts.map +1 -1
- package/dist/storage/ai-cost/analytics.d.ts +2 -1
- package/dist/storage/ai-cost/analytics.d.ts.map +1 -1
- package/dist/storage/ai-cost/codec.d.ts +3 -2
- package/dist/storage/ai-cost/codec.d.ts.map +1 -1
- package/dist/storage/ai-cost/groups.d.ts +51 -0
- package/dist/storage/ai-cost/groups.d.ts.map +1 -0
- package/dist/storage/ai-cost/in-memory.d.ts +11 -1
- package/dist/storage/ai-cost/in-memory.d.ts.map +1 -1
- package/dist/storage/ai-cost/index.d.ts +1 -1
- package/dist/storage/ai-cost/index.d.ts.map +1 -1
- package/dist/storage/ai-cost/provider.d.ts +2 -0
- package/dist/storage/ai-cost/provider.d.ts.map +1 -1
- package/dist/storage/ai-cost/provider.js +29 -13
- package/dist/storage/ai-cost/provider.js.map +3 -3
- package/dist/storage/ai-cost/types.d.ts +64 -15
- package/dist/storage/ai-cost/types.d.ts.map +1 -1
- package/dist/storage/ai-cost/validation.d.ts +2 -1
- package/dist/storage/ai-cost/validation.d.ts.map +1 -1
- package/dist/storage/ai-limits/enforcement.d.ts +14 -0
- package/dist/storage/ai-limits/enforcement.d.ts.map +1 -0
- package/dist/storage/ai-limits/enforcement.js +21 -0
- package/dist/storage/ai-limits/enforcement.js.map +9 -0
- package/dist/storage/ai-limits/errors.d.ts +8 -0
- package/dist/storage/ai-limits/errors.d.ts.map +1 -0
- package/dist/storage/ai-limits/in-memory.d.ts +78 -0
- package/dist/storage/ai-limits/in-memory.d.ts.map +1 -0
- package/dist/storage/ai-limits/index.d.ts +7 -0
- package/dist/storage/ai-limits/index.d.ts.map +1 -0
- package/dist/storage/ai-limits/period.d.ts +4 -0
- package/dist/storage/ai-limits/period.d.ts.map +1 -0
- package/dist/storage/ai-limits/provider.d.ts +85 -0
- package/dist/storage/ai-limits/provider.d.ts.map +1 -0
- package/dist/storage/ai-limits/provider.js +62 -0
- package/dist/storage/ai-limits/provider.js.map +9 -0
- package/dist/storage/ai-limits/types.d.ts +175 -0
- package/dist/storage/ai-limits/types.d.ts.map +1 -0
- package/dist/storage/ai-usage/in-memory.d.ts +4 -0
- package/dist/storage/ai-usage/in-memory.d.ts.map +1 -1
- package/dist/storage/ai-usage/record.d.ts.map +1 -1
- package/dist/storage/ai-usage/types.d.ts +6 -2
- package/dist/storage/ai-usage/types.d.ts.map +1 -1
- package/dist/storage/auth/errors.d.ts +1 -1
- package/dist/storage/auth/errors.d.ts.map +1 -1
- package/dist/storage/auth/in-memory/auth-storage.d.ts +4 -1
- package/dist/storage/auth/in-memory/auth-storage.d.ts.map +1 -1
- package/dist/storage/auth/in-memory/device-authorizations.d.ts +29 -0
- package/dist/storage/auth/in-memory/device-authorizations.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/shared.d.ts +3 -1
- package/dist/storage/auth/in-memory/shared.d.ts.map +1 -1
- package/dist/storage/auth/index.d.ts +2 -1
- package/dist/storage/auth/index.d.ts.map +1 -1
- package/dist/storage/auth/types.d.ts +66 -0
- package/dist/storage/auth/types.d.ts.map +1 -1
- package/dist/storage/connector-connections/provider.js +2 -2
- package/dist/storage/executions/provider.js +1 -1
- package/dist/storage/executions/run-link.d.ts +7 -2
- package/dist/storage/executions/run-link.d.ts.map +1 -1
- package/dist/storage/executions/validation.d.ts.map +1 -1
- package/dist/storage/in-memory/index.d.ts +4 -0
- package/dist/storage/in-memory/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +8 -5
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +51 -38
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/ontology/in-memory/materializations.d.ts +4 -3
- package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
- package/dist/storage/ontology/index.d.ts +1 -1
- package/dist/storage/ontology/index.d.ts.map +1 -1
- package/dist/storage/ontology/materializations.d.ts +7 -3
- package/dist/storage/ontology/materializations.d.ts.map +1 -1
- package/dist/storage/ontology/provider.d.ts +2 -2
- package/dist/storage/ontology/provider.d.ts.map +1 -1
- package/dist/storage/ontology/provider.js +3 -3
- package/dist/storage/pipeline-runs/provider.js +2 -2
- package/dist/storage/projection-runs/provider.js +4 -4
- package/dist/storage/sync-runs/provider.js +2 -2
- package/dist/storage/types.d.ts +5 -1
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/webhook-runs/provider.js +2 -2
- package/dist/storage/workflow-runs/provider.d.ts +1 -1
- package/dist/storage/workflow-runs/provider.js +10 -11
- package/dist/storage/workflow-runs/provider.js.map +1 -1
- package/dist/storage/workflow-runs/types.d.ts +5 -4
- package/dist/storage/workflow-runs/types.d.ts.map +1 -1
- package/dist/syncs/index.js +37 -35
- package/dist/syncs/index.js.map +1 -1
- package/dist/testing/agent-execution.d.ts +3 -1
- package/dist/testing/agent-execution.d.ts.map +1 -1
- package/dist/testing/agent-storage-contract.d.ts.map +1 -1
- package/dist/testing/ai-cost-storage-contract.d.ts.map +1 -1
- package/dist/testing/ai-limit-storage-contract.d.ts +18 -0
- package/dist/testing/ai-limit-storage-contract.d.ts.map +1 -0
- package/dist/testing/ai-model-call-groups-contract.d.ts +6 -0
- package/dist/testing/ai-model-call-groups-contract.d.ts.map +1 -0
- package/dist/testing/ai-usage-storage-contract.d.ts.map +1 -1
- package/dist/testing/auth-storage-contract.d.ts.map +1 -1
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +3758 -1945
- package/dist/testing/index.js.map +15 -13
- package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
- package/dist/testing/queues-contract.d.ts.map +1 -1
- package/dist/webhooks/internal.js +32 -28
- package/dist/webhooks/internal.js.map +2 -2
- package/dist/workers/index.js +2 -2
- package/dist/workflows/agent-step-identity.d.ts +3 -0
- package/dist/workflows/agent-step-identity.d.ts.map +1 -0
- package/dist/workflows/builders.d.ts +2 -3
- package/dist/workflows/builders.d.ts.map +1 -1
- package/dist/workflows/execution.d.ts +1 -1
- package/dist/workflows/execution.d.ts.map +1 -1
- package/dist/workflows/failure.d.ts +1 -1
- package/dist/workflows/failure.d.ts.map +1 -1
- package/dist/workflows/index.d.ts +3 -2
- package/dist/workflows/index.d.ts.map +1 -1
- package/dist/workflows/index.js +53 -45
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/types.d.ts +26 -11
- package/dist/workflows/types.d.ts.map +1 -1
- package/dist/workflows/validation.d.ts +7 -1
- package/dist/workflows/validation.d.ts.map +1 -1
- package/package.json +19 -4
- package/src/actions/types/definitions.ts +24 -2
- package/src/agents/adapters.ts +109 -115
- package/src/agents/authority.ts +214 -32
- package/src/agents/builders.ts +3 -50
- package/src/agents/context-compaction.ts +4 -0
- package/src/agents/dispatch.ts +59 -2
- package/src/agents/errors.ts +5 -2
- package/src/agents/execution.ts +53 -52
- package/src/agents/ids.ts +16 -1
- package/src/agents/index.ts +23 -11
- package/src/agents/message.ts +18 -9
- package/src/agents/model-loop.ts +1023 -0
- package/src/agents/reference.ts +7 -0
- package/src/agents/request.ts +141 -74
- package/src/agents/retired-config.ts +20 -0
- package/src/agents/streams.ts +45 -19
- package/src/agents/tool-catalog.ts +21 -0
- package/src/agents/tool-definition.ts +23 -0
- package/src/agents/types.ts +39 -81
- package/src/agents/validation.ts +34 -180
- package/src/ai-usage/execution.ts +196 -0
- package/src/ai-usage/index.ts +15 -0
- package/src/auth/index.ts +1 -0
- package/src/auth/runtime.ts +8 -0
- package/src/auth/strategy.ts +1 -0
- package/src/auth/types.ts +14 -0
- package/src/authorization/decision.ts +27 -10
- package/src/authorization/grant-kinds.ts +62 -15
- package/src/authorization/index.ts +1 -0
- package/src/authorization/resolve.ts +12 -5
- package/src/authorization/types.ts +7 -5
- package/src/bootstrap/discovery.ts +0 -3
- package/src/error-reporting/types.ts +4 -2
- package/src/errors/catalog.ts +8 -0
- package/src/execution/agent.ts +129 -22
- package/src/execution/authorization.ts +48 -18
- package/src/execution/request.ts +4 -1
- package/src/execution/types.ts +1 -1
- package/src/http/api-routes.ts +63 -0
- package/src/index.ts +36 -7
- package/src/json.ts +9 -0
- package/src/models/catalog.ts +137 -0
- package/src/models/definitions.ts +202 -0
- package/src/models/errors.ts +83 -0
- package/src/models/events.ts +198 -0
- package/src/models/index.ts +89 -71
- package/src/models/language-model.ts +143 -0
- package/src/models/messages.ts +78 -0
- package/src/models/pricing.ts +390 -0
- package/src/models/rate-card.ts +101 -0
- package/src/models/tools.ts +29 -0
- package/src/queues/in-memory.ts +5 -0
- package/src/queues/index.ts +11 -0
- package/src/queues/types.ts +20 -3
- package/src/runtime/create.ts +7 -5
- package/src/runtime/definitions.ts +2 -2
- package/src/runtime/host.ts +3 -2
- package/src/runtime/resolve-definitions.ts +13 -36
- package/src/runtime/sixb.ts +6 -8
- package/src/security/every.ts +0 -4
- package/src/security/grants.ts +55 -11
- package/src/security/index.ts +2 -0
- package/src/security/registry.ts +6 -5
- package/src/security/types.ts +15 -4
- package/src/security/validation.ts +30 -9
- package/src/storage/agents/errors.ts +1 -0
- package/src/storage/agents/in-memory.ts +121 -11
- package/src/storage/agents/index.ts +7 -0
- package/src/storage/agents/provider.ts +150 -6
- package/src/storage/agents/types.ts +73 -16
- package/src/storage/ai-cost/analytics.ts +63 -6
- package/src/storage/ai-cost/codec.ts +37 -12
- package/src/storage/ai-cost/groups.ts +248 -0
- package/src/storage/ai-cost/in-memory.ts +42 -0
- package/src/storage/ai-cost/index.ts +6 -0
- package/src/storage/ai-cost/provider.ts +7 -0
- package/src/storage/ai-cost/types.ts +76 -14
- package/src/storage/ai-cost/validation.ts +147 -17
- package/src/storage/ai-limits/enforcement.ts +68 -0
- package/src/storage/ai-limits/errors.ts +23 -0
- package/src/storage/ai-limits/in-memory.ts +671 -0
- package/src/storage/ai-limits/index.ts +31 -0
- package/src/storage/ai-limits/period.ts +11 -0
- package/src/storage/ai-limits/provider.ts +430 -0
- package/src/storage/ai-limits/types.ts +195 -0
- package/src/storage/ai-usage/in-memory.ts +13 -0
- package/src/storage/ai-usage/record.ts +17 -0
- package/src/storage/ai-usage/types.ts +6 -2
- package/src/storage/auth/errors.ts +6 -0
- package/src/storage/auth/in-memory/auth-storage.ts +69 -0
- package/src/storage/auth/in-memory/device-authorizations.ts +145 -0
- package/src/storage/auth/in-memory/shared.ts +7 -0
- package/src/storage/auth/index.ts +7 -0
- package/src/storage/auth/types.ts +73 -0
- package/src/storage/executions/run-link.ts +16 -6
- package/src/storage/executions/validation.ts +36 -6
- package/src/storage/in-memory/index.ts +48 -4
- package/src/storage/index.ts +52 -1
- package/src/storage/ontology/in-memory/materializations.ts +34 -22
- package/src/storage/ontology/index.ts +1 -0
- package/src/storage/ontology/materializations.ts +8 -3
- package/src/storage/ontology/provider.ts +2 -2
- package/src/storage/types.ts +37 -0
- package/src/storage/workflow-runs/in-memory.ts +3 -3
- package/src/storage/workflow-runs/provider.ts +2 -2
- package/src/storage/workflow-runs/types.ts +6 -3
- package/src/testing/agent-execution.ts +40 -28
- package/src/testing/agent-storage-contract.ts +249 -28
- package/src/testing/ai-cost-storage-contract.ts +96 -8
- package/src/testing/ai-limit-storage-contract.ts +1134 -0
- package/src/testing/ai-model-call-groups-contract.ts +353 -0
- package/src/testing/ai-usage-storage-contract.ts +31 -0
- package/src/testing/auth-storage-contract.ts +85 -0
- package/src/testing/execution-storage-contract.ts +2 -2
- package/src/testing/index.ts +10 -0
- package/src/testing/materializer-storage-contract.ts +170 -2
- package/src/testing/queues-contract.ts +36 -1
- package/src/workflows/agent-step-identity.ts +4 -0
- package/src/workflows/builders.ts +95 -9
- package/src/workflows/execution.ts +2 -2
- package/src/workflows/failure.ts +2 -2
- package/src/workflows/index.ts +3 -0
- package/src/workflows/types.ts +23 -11
- package/src/workflows/validation.ts +100 -7
- package/dist/chunk-6gjqgd3d.js.map +0 -11
- package/dist/chunk-84h6qhmp.js.map +0 -46
- package/dist/chunk-a09jx26t.js +0 -55
- package/dist/chunk-a09jx26t.js.map +0 -11
- package/dist/chunk-dm72y8wt.js.map +0 -10
- package/dist/chunk-drjqm1aa.js.map +0 -15
- package/dist/chunk-gadsm794.js.map +0 -11
- package/dist/chunk-h9kxd41f.js.map +0 -11
- package/dist/chunk-nzw7sm3b.js +0 -137
- package/dist/chunk-nzw7sm3b.js.map +0 -10
- package/dist/chunk-t0jjkep3.js.map +0 -10
- package/dist/chunk-t8t39h7v.js.map +0 -10
- package/dist/chunk-tkdscva6.js.map +0 -37
- package/dist/chunk-v0egge8b.js.map +0 -56
- package/dist/chunk-xdf9yswn.js.map +0 -11
- /package/dist/{chunk-zqysyfjt.js.map → chunk-08m3b6w8.js.map} +0 -0
- /package/dist/{chunk-xkthy56g.js.map → chunk-1kamz6j0.js.map} +0 -0
- /package/dist/{chunk-6d5xdj1q.js.map → chunk-3fqt22c4.js.map} +0 -0
- /package/dist/{chunk-z3zp0bj1.js.map → chunk-407j3msh.js.map} +0 -0
- /package/dist/{chunk-rhrbz7d4.js.map → chunk-4a849fr1.js.map} +0 -0
- /package/dist/{chunk-62c7t4jc.js.map → chunk-4nxeacx7.js.map} +0 -0
- /package/dist/{chunk-cy0n5dms.js.map → chunk-5jcdmjam.js.map} +0 -0
- /package/dist/{chunk-819wnjz8.js.map → chunk-64sr682n.js.map} +0 -0
- /package/dist/{chunk-x2yw73hy.js.map → chunk-7ds9620f.js.map} +0 -0
- /package/dist/{chunk-tbv03sx2.js.map → chunk-9aehf39w.js.map} +0 -0
- /package/dist/{chunk-ezake7g1.js.map → chunk-agsvg9ar.js.map} +0 -0
- /package/dist/{chunk-rnshztfq.js.map → chunk-d63tybny.js.map} +0 -0
- /package/dist/{chunk-vybf6pkp.js.map → chunk-dbc80ad7.js.map} +0 -0
- /package/dist/{chunk-4gz41why.js.map → chunk-dqn23610.js.map} +0 -0
- /package/dist/{chunk-zp2v2rv6.js.map → chunk-ha58tjtt.js.map} +0 -0
- /package/dist/{chunk-f6erf2vv.js.map → chunk-hdz94br2.js.map} +0 -0
- /package/dist/{chunk-dsrkgtnh.js.map → chunk-jq43kdvk.js.map} +0 -0
- /package/dist/{chunk-wtmzkcht.js.map → chunk-k34z5rvh.js.map} +0 -0
- /package/dist/{chunk-htq0qh7z.js.map → chunk-ka3a2ft3.js.map} +0 -0
- /package/dist/{chunk-4h947jd8.js.map → chunk-kt81c11h.js.map} +0 -0
- /package/dist/{chunk-f2rt4vkh.js.map → chunk-n2w475r0.js.map} +0 -0
- /package/dist/{chunk-bhxaq2nn.js.map → chunk-qw9gvjv5.js.map} +0 -0
- /package/dist/{chunk-r0rry8dn.js.map → chunk-rp1mvzb4.js.map} +0 -0
- /package/dist/{chunk-ghteq96b.js.map → chunk-s5y30bc9.js.map} +0 -0
- /package/dist/{chunk-a31h57d5.js.map → chunk-tn7xcs2n.js.map} +0 -0
- /package/dist/{chunk-ea73pzk7.js.map → chunk-vjjv9mrb.js.map} +0 -0
- /package/dist/{chunk-8b55ygje.js.map → chunk-w3e09qqk.js.map} +0 -0
- /package/dist/{chunk-ckxfnx7f.js.map → chunk-wjgm6jjt.js.map} +0 -0
- /package/dist/{chunk-3j7573mj.js.map → chunk-x0qhkqje.js.map} +0 -0
- /package/dist/{chunk-dysw7nsm.js.map → chunk-xdpwpkha.js.map} +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/auth/access-tokens.ts", "../src/auth/csrf.ts", "../src/auth/runtime.ts", "../src/security/applications.ts", "../src/security/errors.ts", "../src/security/membership-policies.ts", "../src/security/validation.ts", "../src/security/builders.ts", "../src/security/every.ts", "../src/security/grants.ts", "../src/security/registry.ts", "../src/storage/auth/errors.ts", "../src/storage/auth/in-memory/shared.ts", "../src/storage/auth/in-memory/access-tokens.ts", "../src/storage/auth/types.ts", "../src/storage/auth/in-memory/device-authorizations.ts", "../src/storage/auth/in-memory/group-memberships.ts", "../src/storage/auth/in-memory/identities.ts", "../src/storage/pagination.ts", "../src/storage/auth/in-memory/invitations.ts", "../src/storage/auth/in-memory/magic-links.ts", "../src/storage/auth/in-memory/oidc-attempts.ts", "../src/storage/auth/in-memory/service-account-group-memberships.ts", "../src/storage/auth/in-memory/service-accounts.ts", "../src/storage/auth/in-memory/sessions.ts", "../src/storage/auth/in-memory/users.ts", "../src/storage/auth/in-memory/auth-storage.ts", "../src/auth/session-cache.ts", "../src/auth/sessions.ts", "../src/auth/types.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { createHash, randomBytes, randomUUID } from \"node:crypto\"\n\nexport const PERSONAL_ACCESS_TOKEN_PREFIX = \"sixb_pat\"\nexport const SERVICE_ACCOUNT_ACCESS_TOKEN_PREFIX = \"sixb_sat\"\n\n// The token prefix makes credentials self-identifying for operators and logs.\n// Validity, revocation, expiration, and permissions still come from storage.\nexport type AccessTokenKind = \"personal\" | \"serviceAccount\"\n\nexport interface AccessTokenParts {\n readonly kind: AccessTokenKind\n readonly tokenId: string\n readonly tokenSecret: string\n}\n\nexport interface AccessTokenCredential extends AccessTokenParts {\n readonly tokenHash: string\n readonly tokenValue: string\n}\n\nconst ACCESS_TOKEN_ID_PATTERN = /^tok_[A-Za-z0-9_-]+$/\nconst ACCESS_TOKEN_SECRET_PATTERN = /^[A-Za-z0-9_-]{32,}$/\n\nexport function generateAccessTokenSecret(): string {\n return randomBytes(32).toString(\"base64url\")\n}\n\nexport function hashAccessTokenSecret(secret: string): string {\n return createHash(\"sha256\").update(secret).digest(\"hex\")\n}\n\nexport function formatAccessTokenValue(\n kind: AccessTokenKind,\n tokenId: string,\n tokenSecret: string\n): string {\n const prefix = accessTokenPrefixForKind(kind)\n\n if (!ACCESS_TOKEN_ID_PATTERN.test(tokenId)) {\n throw new Error(\"[Sixb] Access token ids must start with 'tok_' and be URL-safe.\")\n }\n\n if (!ACCESS_TOKEN_SECRET_PATTERN.test(tokenSecret)) {\n throw new Error(\"[Sixb] Access token secrets must be at least 32 URL-safe characters.\")\n }\n\n return `${prefix}_${tokenId}.${tokenSecret}`\n}\n\nexport function parseAccessTokenValue(value: string | undefined): AccessTokenParts | null {\n // Parsing is intentionally non-throwing so auth paths can treat malformed\n // credentials exactly like missing credentials.\n if (!value) {\n return null\n }\n\n const firstDot = value.indexOf(\".\")\n if (firstDot <= 0 || firstDot !== value.lastIndexOf(\".\") || firstDot === value.length - 1) {\n return null\n }\n\n const tokenLabel = value.slice(0, firstDot)\n const tokenSecret = value.slice(firstDot + 1)\n const kind = accessTokenKindFromLabel(tokenLabel)\n if (!kind || !ACCESS_TOKEN_SECRET_PATTERN.test(tokenSecret)) {\n return null\n }\n\n const tokenId = tokenLabel.slice(`${accessTokenPrefixForKind(kind)}_`.length)\n if (!ACCESS_TOKEN_ID_PATTERN.test(tokenId)) {\n return null\n }\n\n return { kind, tokenId, tokenSecret }\n}\n\nexport function getBearerAccessTokenValue(request: Request): string | null {\n const header = request.headers.get(\"authorization\")\n if (!header) {\n return null\n }\n\n const [scheme, token, extra] = header.trim().split(/\\s+/)\n if (scheme?.toLowerCase() !== \"bearer\" || !token || extra) {\n return null\n }\n\n return token\n}\n\nexport function createAccessTokenCredential(\n kind: AccessTokenKind,\n tokenId = `tok_${randomUUID()}`\n): AccessTokenCredential {\n const tokenSecret = generateAccessTokenSecret()\n // Callers should return tokenValue once, then persist only tokenHash.\n return {\n kind,\n tokenId,\n tokenSecret,\n tokenHash: hashAccessTokenSecret(tokenSecret),\n tokenValue: formatAccessTokenValue(kind, tokenId, tokenSecret),\n }\n}\n\nfunction accessTokenPrefixForKind(kind: AccessTokenKind): string {\n switch (kind) {\n case \"personal\":\n return PERSONAL_ACCESS_TOKEN_PREFIX\n case \"serviceAccount\":\n return SERVICE_ACCOUNT_ACCESS_TOKEN_PREFIX\n }\n}\n\nfunction accessTokenKindFromLabel(label: string): AccessTokenKind | null {\n if (label.startsWith(`${PERSONAL_ACCESS_TOKEN_PREFIX}_`)) {\n return \"personal\"\n }\n\n if (label.startsWith(`${SERVICE_ACCOUNT_ACCESS_TOKEN_PREFIX}_`)) {\n return \"serviceAccount\"\n }\n\n return null\n}\n",
|
|
6
|
+
"import { randomBytes, timingSafeEqual } from \"node:crypto\"\nimport { getCookie } from \"./cookies\"\n\nexport const CSRF_HEADER_NAME = \"x-sixb-csrf\"\n\nexport function generateCsrfToken(): string {\n return randomBytes(32).toString(\"base64url\")\n}\n\nexport function isCsrfExemptMethod(method: string): boolean {\n const normalized = method.toUpperCase()\n return normalized === \"GET\" || normalized === \"HEAD\" || normalized === \"OPTIONS\"\n}\n\nexport function verifyDoubleSubmitCsrf(\n request: Request,\n options: { readonly cookieName: string; readonly headerName?: string }\n): boolean {\n if (isCsrfExemptMethod(request.method)) {\n return true\n }\n\n const cookieValue = getCookie(request, options.cookieName)\n const headerValue = request.headers.get(options.headerName ?? CSRF_HEADER_NAME)\n\n if (!cookieValue || !headerValue) {\n return false\n }\n\n return safeEqual(cookieValue, headerValue)\n}\n\nfunction safeEqual(left: string, right: string): boolean {\n const leftBytes = Buffer.from(left)\n const rightBytes = Buffer.from(right)\n if (leftBytes.length !== rightBytes.length) {\n return false\n }\n\n return timingSafeEqual(leftBytes, rightBytes)\n}\n",
|
|
7
|
+
"import { randomUUID } from \"node:crypto\"\nimport {\n type AuthorizationContext,\n canAccessApplication,\n resolveAuthorizationContext,\n} from \"../authorization\"\nimport {\n canPerformMembershipOperation,\n type GroupReference,\n type MembershipOperation,\n type MembershipPolicyScope,\n missingMembershipGroupIds,\n resolveMembershipPolicyScope,\n type SecurityDefinitionCatalog,\n} from \"../security\"\nimport type { Storage } from \"../storage\"\nimport {\n type AccessTokenRecord,\n type AuthStorage,\n AuthStorageError,\n type InvitationRecord,\n type ServiceAccountGroupMembershipRecord,\n type ServiceAccountRecord,\n type SessionRecord,\n type UserRecord,\n} from \"../storage/auth\"\nimport { paginate } from \"../storage/pagination\"\nimport {\n createAccessTokenCredential,\n getBearerAccessTokenValue,\n hashAccessTokenSecret,\n parseAccessTokenValue,\n} from \"./access-tokens\"\nimport type { AuthSessionAudience } from \"./audience\"\nimport {\n getCookie,\n type ResolvedAuthCookieOptions,\n resolveAuthCookieOptionsForAudience,\n} from \"./cookies\"\nimport { AuthRuntimeError } from \"./errors\"\nimport { SessionCache } from \"./session-cache\"\nimport { hashSessionSecret, parseSessionCookieValue } from \"./sessions\"\nimport type {\n AuthenticatedAuthSession,\n AuthenticatedRequestAuthSession,\n AuthenticatedUserRequestSession,\n AuthRequestResult,\n AuthSessionResolutionOptions,\n AuthSessionResult,\n AuthStrategy,\n CreateAccessTokenResult,\n CreatePersonalAccessTokenInput,\n CreateServiceAccountAccessTokenInput,\n CreateServiceAccountAccessTokenResult,\n CreateServiceAccountInput,\n CreateServiceAccountResult,\n DisableServiceAccountInput,\n DisableServiceAccountResult,\n GetInvitationOptionsResult,\n GetMembershipOptionsResult,\n InvitationDeliveryAuthStrategy,\n InvitationGroupOption,\n InvitationRecipientStatus,\n InviteDeliveryResult,\n InviteDeliveryStatus,\n InviteUserInput,\n InviteUserOptions,\n InviteUserResult,\n ListInvitationsInput,\n ListInvitationsResult,\n ListMembersInput,\n ListMembersResult,\n ListPersonalAccessTokensResult,\n ListServiceAccountAccessTokensInput,\n ListServiceAccountAccessTokensResult,\n ListServiceAccountsResult,\n MemberSummary,\n MembershipCapabilities,\n Principal,\n ReactivateMemberInput,\n ReactivateMemberResult,\n ResolvedAuthConfig,\n RevokeAccessTokenResult,\n RevokeInvitationInput,\n RevokeInvitationResult,\n RevokePersonalAccessTokenInput,\n RevokeServiceAccountAccessTokenInput,\n RevokeServiceAccountAccessTokenResult,\n SecurityContext,\n SixbAuthConfig,\n SuspendMemberInput,\n SuspendMemberResult,\n UpdateMemberGroupsInput,\n UpdateMemberGroupsResult,\n} from \"./types\"\nimport {\n assertNonEmpty,\n isInvitationDeliveryAuthStrategy,\n normalizePagination,\n resolveAuthConfig,\n resolveAuthSessionAudience,\n resolveInvitationExpiresAt,\n sanitizeReturnTo,\n} from \"./validation\"\n\nexport {\n DEFAULT_AUTH_INVITATION_TTL_MS,\n DEFAULT_AUTH_SESSION_CACHE_TTL_MS,\n DEFAULT_AUTH_SESSION_IDLE_TIMEOUT_MS,\n DEFAULT_AUTH_SESSION_RENEWAL_WINDOW_MS,\n MAX_AUTH_INVITATION_TTL_MS,\n resolveAuthConfig,\n} from \"./validation\"\n\n// Throttle `lastSeenAt` writes: only refresh when the previous value is older\n// than this, so an active session does not incur a write on every request.\nconst SESSION_TOUCH_INTERVAL_MS = 60_000\nconst ACCESS_TOKEN_TOUCH_INTERVAL_MS = 60_000\n\nexport interface AuthRuntimeOptions {\n readonly projectId: string\n readonly storage: Storage\n readonly security: SecurityDefinitionCatalog\n readonly config?: SixbAuthConfig\n}\n\nexport class AuthRuntime {\n private readonly projectId: string\n private readonly storage: Storage\n private readonly security: SecurityDefinitionCatalog\n private readonly config: ResolvedAuthConfig\n private readonly sessionCache: SessionCache | null\n\n constructor(options: AuthRuntimeOptions) {\n this.projectId = options.projectId\n this.storage = options.storage\n this.security = options.security\n this.config = resolveAuthConfig(options.config)\n this.sessionCache =\n this.config.session.cacheTtlMs > 0 ? new SessionCache(this.config.session.cacheTtlMs) : null\n\n if (this.isEnabled() && !this.storage.auth) {\n throw new AuthRuntimeError(\n \"auth_storage_missing\",\n \"[Sixb] Auth is enabled but storage.auth is not configured.\"\n )\n }\n }\n\n isEnabled(): boolean {\n const strategy = this.config.strategy\n return strategy !== null && strategy.kind !== \"disabled\" && strategy.disabled !== true\n }\n\n getStrategy(): AuthStrategy | null {\n return this.config.strategy\n }\n\n createSessionDeadlines(now: Date): {\n readonly expiresAt: Date\n readonly absoluteExpiresAt?: Date\n } {\n const absoluteTimeoutMs = this.config.session.absoluteTimeoutMs\n return {\n expiresAt: new Date(now.getTime() + this.config.session.idleTimeoutMs),\n ...(absoluteTimeoutMs === undefined\n ? {}\n : { absoluteExpiresAt: new Date(now.getTime() + absoluteTimeoutMs) }),\n }\n }\n\n getCookieOptions(options: AuthSessionResolutionOptions = {}): ResolvedAuthCookieOptions {\n return resolveAuthCookieOptionsForAudience(this.config.cookies, options.audience)\n }\n\n assertCanServeHttp(params: { readonly production: boolean }): void {\n const strategy = this.config.strategy\n\n if (!strategy) {\n if (params.production) {\n throw new AuthRuntimeError(\n \"production_auth_required\",\n \"[SixbServer] Auth is required in production. Configure auth or use an explicit disabled auth strategy.\"\n )\n }\n return\n }\n\n if (params.production && strategy.developmentOnly) {\n throw new AuthRuntimeError(\n \"production_auth_required\",\n `[SixbServer] Auth strategy '${strategy.id}' is development-only and cannot be used in production.`\n )\n }\n\n if (\n params.production &&\n (strategy.kind === \"disabled\" || strategy.disabled === true) &&\n strategy.allowDisabledInProduction !== true\n ) {\n throw new AuthRuntimeError(\n \"production_auth_required\",\n \"[SixbServer] Disabled auth in production requires allowDisabledInProduction: true.\"\n )\n }\n }\n\n async getSession(\n request: Request,\n options?: AuthSessionResolutionOptions & { readonly credentialSource?: \"session\" }\n ): Promise<AuthSessionResult>\n async getSession(\n request: Request,\n options: AuthSessionResolutionOptions & { readonly credentialSource: \"accessToken\" | \"any\" }\n ): Promise<AuthRequestResult>\n async getSession(\n request: Request,\n options: AuthSessionResolutionOptions\n ): Promise<AuthRequestResult>\n async getSession(\n request: Request,\n options: AuthSessionResolutionOptions = {}\n ): Promise<AuthSessionResult | AuthRequestResult> {\n if (!this.isEnabled()) {\n return { authenticated: false, reason: \"auth_disabled\" }\n }\n\n const audience = resolveAuthSessionAudience(options.audience)\n const credentialSource = options.credentialSource ?? \"session\"\n\n if (credentialSource !== \"session\") {\n const authorizationHeader = request.headers.get(\"authorization\")\n const tokenValue = getBearerAccessTokenValue(request)\n if (tokenValue) {\n return this.resolveAccessTokenSession(request, tokenValue)\n }\n\n if (authorizationHeader) {\n return { authenticated: false, reason: \"invalid_access_token\" }\n }\n\n if (credentialSource === \"accessToken\") {\n return { authenticated: false, reason: \"missing_access_token\" }\n }\n }\n\n return this.resolveCookieSession(request, audience, options.sessionActivity)\n }\n\n private async resolveCookieSession(\n request: Request,\n audience: ReturnType<typeof resolveAuthSessionAudience>,\n activity: AuthSessionResolutionOptions[\"sessionActivity\"]\n ): Promise<AuthSessionResult> {\n const cookieOptions = this.getCookieOptions({ audience })\n const cookieValue = getCookie(request, cookieOptions.sessionCookieName)\n if (!cookieValue) {\n return { authenticated: false, reason: \"missing_cookie\" }\n }\n\n const parts = parseSessionCookieValue(cookieValue)\n if (!parts) {\n return { authenticated: false, reason: \"invalid_cookie\" }\n }\n\n const tokenHash = hashSessionSecret(parts.sessionSecret)\n const nowMs = Date.now()\n\n const cached = this.sessionCache?.get({\n sessionId: parts.sessionId,\n tokenHash,\n audience,\n nowMs,\n })\n if (cached) {\n if (activity !== \"foreground\" || !this.canRenewSession(cached.session, nowMs)) {\n return cached\n }\n this.sessionCache?.invalidate(parts.sessionId)\n }\n\n const storage = this.requireAuthStorage()\n const now = new Date(nowMs)\n let session = await storage.sessions.findValidByTokenHash({\n projectId: this.projectId,\n id: parts.sessionId,\n audience,\n tokenHash,\n now,\n })\n\n if (!session) {\n return { authenticated: false, reason: \"invalid_session\" }\n }\n\n let sessionRenewed = false\n if (activity === \"foreground\" && this.canRenewSession(session, nowMs)) {\n const renewed = await storage.sessions.renewIfValid({\n projectId: this.projectId,\n id: parts.sessionId,\n audience,\n tokenHash,\n now,\n expiresAt: this.getRenewedSessionExpiresAt(session, nowMs),\n })\n if (!renewed) {\n this.sessionCache?.invalidate(parts.sessionId)\n return { authenticated: false, reason: \"invalid_session\" }\n }\n session = renewed\n sessionRenewed = true\n }\n\n const user = await storage.users.getById({\n projectId: this.projectId,\n id: session.userId,\n })\n\n if (!user) {\n return { authenticated: false, reason: \"missing_user\" }\n }\n\n if (user.status === \"suspended\") {\n return { authenticated: false, reason: \"suspended_user\" }\n }\n\n const memberships = await storage.groupMemberships.listForUser({\n projectId: this.projectId,\n userId: user.id,\n })\n\n if (!sessionRenewed) {\n await this.touchSessionLastSeen(storage, session, now)\n }\n\n const result: AuthenticatedAuthSession = {\n authenticated: true,\n credentialSource: \"session\",\n principal: { type: \"user\", id: user.id },\n user,\n session,\n groupIds: memberships.map((membership) => membership.groupId),\n }\n\n this.sessionCache?.set({\n sessionId: parts.sessionId,\n tokenHash,\n audience,\n session: result,\n nowMs,\n sessionExpiresAtMs: session.expiresAt.getTime(),\n sessionAbsoluteExpiresAtMs: session.absoluteExpiresAt?.getTime(),\n })\n\n return sessionRenewed ? { ...result, sessionRenewed: true } : result\n }\n\n private canRenewSession(session: SessionRecord, nowMs: number): boolean {\n if (session.expiresAt.getTime() - nowMs > this.config.session.renewalWindowMs) {\n return false\n }\n\n return this.getRenewedSessionExpiresAt(session, nowMs).getTime() > session.expiresAt.getTime()\n }\n\n private getRenewedSessionExpiresAt(session: SessionRecord, nowMs: number): Date {\n const idleExpiresAtMs = nowMs + this.config.session.idleTimeoutMs\n return new Date(\n session.absoluteExpiresAt\n ? Math.min(idleExpiresAtMs, session.absoluteExpiresAt.getTime())\n : idleExpiresAtMs\n )\n }\n\n private async resolveAccessTokenSession(\n request: Request,\n tokenValue: string\n ): Promise<AuthRequestResult> {\n const parts = parseAccessTokenValue(tokenValue)\n if (!parts) {\n return { authenticated: false, reason: \"invalid_access_token\" }\n }\n\n const storage = this.requireAuthStorage()\n const now = new Date()\n const accessToken = await storage.accessTokens.findValidByTokenHash({\n projectId: this.projectId,\n id: parts.tokenId,\n kind: parts.kind,\n tokenHash: hashAccessTokenSecret(parts.tokenSecret),\n now,\n })\n\n if (!accessToken) {\n return { authenticated: false, reason: \"invalid_access_token\" }\n }\n\n await this.touchAccessTokenLastUsed(storage, accessToken, request, now)\n\n if (accessToken.subjectType === \"user\") {\n const user = await storage.users.getById({\n projectId: this.projectId,\n id: accessToken.subjectId,\n })\n\n if (!user) {\n return { authenticated: false, reason: \"missing_user\" }\n }\n\n if (user.status === \"suspended\") {\n return { authenticated: false, reason: \"suspended_user\" }\n }\n\n const memberships = await storage.groupMemberships.listForUser({\n projectId: this.projectId,\n userId: user.id,\n })\n\n return {\n authenticated: true,\n credentialSource: \"accessToken\",\n principal: { type: \"user\", id: user.id },\n user,\n accessToken,\n groupIds: constrainTokenGroupIds(\n memberships.map((membership) => membership.groupId),\n accessToken\n ),\n }\n }\n\n const serviceAccount = await storage.serviceAccounts.getById({\n projectId: this.projectId,\n id: accessToken.subjectId,\n })\n\n if (!serviceAccount) {\n return { authenticated: false, reason: \"missing_service_account\" }\n }\n\n if (serviceAccount.status === \"suspended\") {\n return { authenticated: false, reason: \"suspended_service_account\" }\n }\n\n const memberships = await storage.serviceAccountGroupMemberships.listForServiceAccount({\n projectId: this.projectId,\n serviceAccountId: serviceAccount.id,\n })\n\n return {\n authenticated: true,\n credentialSource: \"accessToken\",\n principal: { type: \"serviceAccount\", id: serviceAccount.id },\n serviceAccount,\n accessToken,\n groupIds: constrainTokenGroupIds(\n memberships.map((membership) => membership.groupId),\n accessToken\n ),\n }\n }\n\n /**\n * Evict a session from the in-process cache. Call this when a session is revoked\n * (e.g. sign-out) so the cached result is dropped before its TTL would expire.\n */\n invalidateSession(sessionId: string): void {\n this.sessionCache?.invalidate(sessionId)\n }\n\n // Best-effort refresh of `lastSeenAt` for the active-sessions view. Throttled,\n // and never allowed to fail an otherwise-valid request.\n private async touchSessionLastSeen(\n storage: AuthStorage,\n session: { readonly id: string; readonly lastSeenAt?: Date },\n now: Date\n ): Promise<void> {\n const lastSeen = session.lastSeenAt?.getTime() ?? 0\n if (now.getTime() - lastSeen < SESSION_TOUCH_INTERVAL_MS) {\n return\n }\n try {\n await storage.sessions.touch({ projectId: this.projectId, id: session.id, lastSeenAt: now })\n } catch {\n // Touch is non-critical; ignore failures so auth still succeeds.\n }\n }\n\n private async touchAccessTokenLastUsed(\n storage: AuthStorage,\n accessToken: AccessTokenRecord,\n request: Request,\n now: Date\n ): Promise<void> {\n const lastUsed = accessToken.lastUsedAt?.getTime() ?? 0\n if (now.getTime() - lastUsed < ACCESS_TOKEN_TOUCH_INTERVAL_MS) {\n return\n }\n\n try {\n await storage.accessTokens.touch({\n projectId: this.projectId,\n id: accessToken.id,\n lastUsedAt: now,\n userAgent: request.headers.get(\"user-agent\")?.trim() || undefined,\n ipAddress: resolveRequestIpAddress(request),\n })\n } catch {\n // Touch is non-critical; ignore failures so auth still succeeds.\n }\n }\n\n async requirePrincipal(\n request: Request,\n options: AuthSessionResolutionOptions = {}\n ): Promise<Principal> {\n const session = await this.getSession(request, options)\n if (!session.authenticated) {\n throw new AuthRuntimeError(\"authentication_required\", \"[Sixb] Authentication is required.\")\n }\n\n return session.principal\n }\n\n async requireUser(\n request: Request,\n options: AuthSessionResolutionOptions = {}\n ): Promise<AuthenticatedAuthSession> {\n const session = await this.getSession(request, { ...options, credentialSource: \"session\" })\n if (!session.authenticated) {\n throw new AuthRuntimeError(\"authentication_required\", \"[Sixb] Authentication is required.\")\n }\n\n return session\n }\n\n async requireUserRequest(\n request: Request,\n options: AuthSessionResolutionOptions = {}\n ): Promise<AuthenticatedUserRequestSession> {\n const session = await this.getSession(request, { ...options, credentialSource: \"any\" })\n if (!session.authenticated) {\n throw new AuthRuntimeError(\"authentication_required\", \"[Sixb] Authentication is required.\")\n }\n\n if (!isAuthenticatedUserRequestSession(session)) {\n throw new AuthRuntimeError(\"authorization_denied\", \"[Sixb] User authentication is required.\")\n }\n\n return session\n }\n\n async createSecurityContext(\n request: Request,\n options: AuthSessionResolutionOptions = {}\n ): Promise<SecurityContext> {\n const session = await this.requireUser(request, options)\n return {\n principal: session.principal,\n sessionId: session.session.id,\n projectId: this.projectId,\n correlationId: resolveCorrelationId(request),\n }\n }\n\n /**\n * Resolve the authenticated principal's authorization context for a request.\n *\n * Grants resolve eagerly (`groups -> roles -> grants`, subtype-expanded), so the returned\n * context supports synchronous checks when Core binds a request execution SDK.\n */\n async createAuthorizationContext(\n request: Request,\n options: AuthSessionResolutionOptions = {}\n ): Promise<AuthorizationContext> {\n const session = await this.getSession(request, options)\n if (!session.authenticated) {\n throw new AuthRuntimeError(\"authentication_required\", \"[Sixb] Authentication is required.\")\n }\n\n return this.contextFromSession(session)\n }\n\n /**\n * Build an authorization context from an already-resolved session, so callers\n * that resolve the session themselves (e.g. the server auth guard) don't read\n * the request twice.\n */\n contextFromSession(session: AuthenticatedRequestAuthSession): AuthorizationContext {\n return resolveAuthorizationContext({\n principal: session.principal,\n sessionId: session.credentialSource === \"session\" ? session.session.id : undefined,\n groupIds: session.groupIds,\n roles: this.security.listResolvedRoles(),\n })\n }\n\n async listPersonalAccessTokens(\n request: Request,\n options: AuthSessionResolutionOptions = {}\n ): Promise<ListPersonalAccessTokensResult> {\n const session = await this.requireUserRequest(request, options)\n const storage = this.requireAuthStorage()\n const result = await storage.accessTokens.list({\n projectId: this.projectId,\n kind: \"personal\",\n subjectType: \"user\",\n subjectId: session.user.id,\n includeRevoked: true,\n order: \"desc\",\n limit: 100,\n })\n\n return { accessTokens: result.accessTokens }\n }\n\n async createPersonalAccessToken(\n request: Request,\n input: CreatePersonalAccessTokenInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<CreateAccessTokenResult> {\n const session = await this.requireUserRequest(request, options)\n const storage = this.requireAuthStorage()\n // A personal token can only carry groups the caller currently belongs to.\n const groupIds = constrainRequestedGroupIds(input.groupIds, session.groupIds, {\n subject: \"personal access token\",\n })\n const credential = createAccessTokenCredential(\"personal\")\n const accessToken = await storage.accessTokens.create({\n id: credential.tokenId,\n projectId: this.projectId,\n name: input.name,\n kind: \"personal\",\n subjectType: \"user\",\n subjectId: session.user.id,\n tokenHash: credential.tokenHash,\n groupIds,\n createdByPrincipal: session.principal,\n createdBySessionId: session.credentialSource === \"session\" ? session.session.id : undefined,\n createdAt: new Date(),\n expiresAt: input.expiresAt,\n })\n\n return { accessToken, tokenValue: credential.tokenValue }\n }\n\n async revokePersonalAccessToken(\n request: Request,\n input: RevokePersonalAccessTokenInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<RevokeAccessTokenResult> {\n const session = await this.requireUserRequest(request, options)\n const storage = this.requireAuthStorage()\n const token = await storage.accessTokens.getById({\n projectId: this.projectId,\n id: input.tokenId,\n })\n // Personal tokens are self-service only. A foreign or missing token id is\n // reported identically so callers cannot probe other principals' tokens.\n if (\n !token ||\n token.kind !== \"personal\" ||\n token.subjectType !== \"user\" ||\n token.subjectId !== session.user.id\n ) {\n throw missingAccessTokenError(input.tokenId, this.projectId)\n }\n\n const accessToken = await storage.accessTokens.revoke({\n projectId: this.projectId,\n id: input.tokenId,\n revokedAt: new Date(),\n })\n\n return { accessToken }\n }\n\n async listServiceAccounts(\n request: Request,\n options: AuthSessionResolutionOptions = {}\n ): Promise<ListServiceAccountsResult> {\n const session = await this.requireUserRequest(request, options)\n const storage = this.requireAuthStorage()\n const result = await storage.serviceAccounts.list({\n projectId: this.projectId,\n order: \"desc\",\n limit: 100,\n })\n const withGroups = await Promise.all(\n result.serviceAccounts.map(async (serviceAccount) => ({\n serviceAccount,\n groupIds: await this.listServiceAccountGroupIds(storage, serviceAccount.id),\n }))\n )\n\n // A caller only sees the service accounts it is allowed to manage, so\n // listing never leaks the groups of more-privileged accounts.\n return {\n serviceAccounts: withGroups.filter(({ groupIds }) =>\n callerCanManageServiceAccount(session.groupIds, groupIds)\n ),\n }\n }\n\n async createServiceAccount(\n request: Request,\n input: CreateServiceAccountInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<CreateServiceAccountResult> {\n const session = await this.requireUserRequest(request, options)\n const storage = this.requireAuthStorage()\n // A caller can only place a service account in groups it itself belongs to.\n const groupIds =\n constrainRequestedGroupIds(input.groupIds, session.groupIds, {\n subject: \"service account\",\n }) ?? []\n const now = new Date()\n const serviceAccount = await storage.serviceAccounts.create({\n id: input.id ?? `svc_${randomUUID()}`,\n projectId: this.projectId,\n name: input.name,\n description: input.description,\n createdByPrincipal: session.principal,\n createdBySessionId: session.credentialSource === \"session\" ? session.session.id : undefined,\n createdAt: now,\n updatedAt: now,\n })\n const groupMemberships: ServiceAccountGroupMembershipRecord[] = []\n for (const groupId of groupIds) {\n groupMemberships.push(\n await storage.serviceAccountGroupMemberships.upsert({\n projectId: this.projectId,\n serviceAccountId: serviceAccount.id,\n groupId,\n source: \"manual\",\n createdAt: now,\n })\n )\n }\n\n return { serviceAccount, groupMemberships }\n }\n\n async disableServiceAccount(\n request: Request,\n input: DisableServiceAccountInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<DisableServiceAccountResult> {\n const session = await this.requireUserRequest(request, options)\n const storage = this.requireAuthStorage()\n const { serviceAccount, groupIds } = await this.requireManageableServiceAccount(\n storage,\n session.groupIds,\n input.serviceAccountId\n )\n const updated = await storage.serviceAccounts.update({\n projectId: this.projectId,\n id: serviceAccount.id,\n status: \"suspended\",\n updatedAt: new Date(),\n })\n\n return { serviceAccount: updated, groupIds }\n }\n\n async listServiceAccountAccessTokens(\n request: Request,\n input: ListServiceAccountAccessTokensInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<ListServiceAccountAccessTokensResult> {\n const session = await this.requireUserRequest(request, options)\n const storage = this.requireAuthStorage()\n const { serviceAccount } = await this.requireManageableServiceAccount(\n storage,\n session.groupIds,\n input.serviceAccountId\n )\n const result = await storage.accessTokens.list({\n projectId: this.projectId,\n kind: \"serviceAccount\",\n subjectType: \"serviceAccount\",\n subjectId: serviceAccount.id,\n includeRevoked: true,\n order: \"desc\",\n limit: 100,\n })\n\n return { serviceAccount, accessTokens: result.accessTokens }\n }\n\n async createServiceAccountAccessToken(\n request: Request,\n input: CreateServiceAccountAccessTokenInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<CreateServiceAccountAccessTokenResult> {\n const session = await this.requireUserRequest(request, options)\n const storage = this.requireAuthStorage()\n const { serviceAccount, groupIds: serviceAccountGroupIds } =\n await this.requireManageableServiceAccount(storage, session.groupIds, input.serviceAccountId)\n\n if (serviceAccount.status === \"suspended\") {\n throw new AuthStorageError(\n \"suspended_service_account\",\n `[Sixb] Service account '${input.serviceAccountId}' is suspended for project '${this.projectId}'.`\n )\n }\n\n // The token can only carry groups the service account already holds; the\n // manageability check above guarantees those are a subset of the caller's\n // own groups, so the caller can never mint privileges it lacks.\n const groupIds = constrainRequestedGroupIds(input.groupIds, serviceAccountGroupIds, {\n subject: \"service account token\",\n })\n const credential = createAccessTokenCredential(\"serviceAccount\")\n const accessToken = await storage.accessTokens.create({\n id: credential.tokenId,\n projectId: this.projectId,\n name: input.name,\n kind: \"serviceAccount\",\n subjectType: \"serviceAccount\",\n subjectId: serviceAccount.id,\n tokenHash: credential.tokenHash,\n groupIds,\n createdByPrincipal: session.principal,\n createdBySessionId: session.credentialSource === \"session\" ? session.session.id : undefined,\n createdAt: new Date(),\n expiresAt: input.expiresAt,\n })\n\n return { accessToken, tokenValue: credential.tokenValue, serviceAccount }\n }\n\n async revokeServiceAccountAccessToken(\n request: Request,\n input: RevokeServiceAccountAccessTokenInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<RevokeServiceAccountAccessTokenResult> {\n const session = await this.requireUserRequest(request, options)\n const storage = this.requireAuthStorage()\n const { serviceAccount } = await this.requireManageableServiceAccount(\n storage,\n session.groupIds,\n input.serviceAccountId\n )\n const token = await storage.accessTokens.getById({\n projectId: this.projectId,\n id: input.tokenId,\n })\n // The token must belong to the service account named in the request.\n if (\n !token ||\n token.kind !== \"serviceAccount\" ||\n token.subjectType !== \"serviceAccount\" ||\n token.subjectId !== serviceAccount.id\n ) {\n throw missingAccessTokenError(input.tokenId, this.projectId)\n }\n\n const accessToken = await storage.accessTokens.revoke({\n projectId: this.projectId,\n id: input.tokenId,\n revokedAt: new Date(),\n })\n\n return { serviceAccount, accessToken }\n }\n\n /**\n * Resolve a service account the caller is allowed to manage.\n *\n * A caller may manage a service account only when it belongs to every group\n * the account is in (\"you can manage what you could have created\"). This\n * confines token minting, disabling, and revocation to privileges the caller\n * already holds and prevents a service-account token from outliving the\n * caller's own access. Missing and non-manageable accounts raise the same\n * error so callers cannot probe which privileged accounts exist.\n */\n private async requireManageableServiceAccount(\n storage: AuthStorage,\n callerGroupIds: readonly string[],\n serviceAccountId: string\n ): Promise<{\n readonly serviceAccount: ServiceAccountRecord\n readonly groupIds: readonly string[]\n }> {\n const serviceAccount = await storage.serviceAccounts.getById({\n projectId: this.projectId,\n id: serviceAccountId,\n })\n const groupIds = serviceAccount\n ? await this.listServiceAccountGroupIds(storage, serviceAccountId)\n : []\n\n if (!serviceAccount || !callerCanManageServiceAccount(callerGroupIds, groupIds)) {\n throw new AuthStorageError(\n \"missing_service_account\",\n `[Sixb] Service account '${serviceAccountId}' not found for project '${this.projectId}'.`\n )\n }\n\n return { serviceAccount, groupIds }\n }\n\n private async listServiceAccountGroupIds(\n storage: AuthStorage,\n serviceAccountId: string\n ): Promise<readonly string[]> {\n const memberships = await storage.serviceAccountGroupMemberships.listForServiceAccount({\n projectId: this.projectId,\n serviceAccountId,\n })\n return memberships.map((membership) => membership.groupId)\n }\n\n async getInvitationOptions(\n request: Request,\n options: AuthSessionResolutionOptions = {}\n ): Promise<GetInvitationOptionsResult> {\n const session = await this.requireUser(request, options)\n const scope = this.resolveMembershipPolicyScopeForUser(session.groupIds)\n const inviteScope = scope.operations.invite\n const groups = this.scopedGroupOptions(inviteScope.groupIds)\n const hasInviteMembershipPolicy = inviteScope.policyIds.length > 0\n\n return {\n groups,\n canInviteWithoutGroups: hasInviteMembershipPolicy,\n capabilities: {\n createInvitation: this.resolveCreateInvitationCapability({\n canInvite: hasInviteMembershipPolicy,\n }),\n },\n }\n }\n\n /**\n * Resolve what a caller's membership policies let it do, from its groups alone.\n *\n * This is the public form of the question the member-admin routes ask internally. It takes groups\n * rather than a `Request` so project code and tests can ask it without a session — an\n * `AuthorizationContext` carries `groupIds` for exactly this. Definitions and ids are both accepted,\n * because a session hands you ids and your own code has the definition.\n */\n getMembershipCapabilities(input: {\n readonly callerGroups: readonly GroupReference[]\n }): MembershipCapabilities {\n return membershipCapabilities(\n this.resolveMembershipPolicyScopeForUser(groupIdsOf(input.callerGroups))\n )\n }\n\n async getMembershipOptions(\n request: Request,\n options: AuthSessionResolutionOptions = {}\n ): Promise<GetMembershipOptionsResult> {\n const session = await this.requireUser(request, options)\n const scope = this.resolveMembershipPolicyScopeForUser(session.groupIds)\n\n return {\n // The member-admin edit-groups dialog assigns from the `assignGroups` scope.\n groups: this.scopedGroupOptions(scope.operations.assignGroups.groupIds),\n capabilities: membershipCapabilities(scope).holds,\n }\n }\n\n async listMembers(\n request: Request,\n input: ListMembersInput = {},\n options: AuthSessionResolutionOptions = {}\n ): Promise<ListMembersResult> {\n const session = await this.requireUser(request, options)\n const storage = this.requireAuthStorage()\n const scope = this.resolveMembershipPolicyScopeForUser(session.groupIds)\n const { limit, offset } = normalizePagination(input)\n\n // First slice loads all users, attaches groups, then filters and paginates in\n // memory. Adequate for expected member counts; revisit with indexed queries if\n // projects grow large.\n const result = await storage.users.list({ projectId: this.projectId, order: input.order })\n\n const members: MemberSummary[] = []\n for (const user of result.users) {\n const groupIds = (\n await storage.groupMemberships.listForUser({ projectId: this.projectId, userId: user.id })\n ).map((membership) => membership.groupId)\n\n // Visibility is scope-based: a member is listed when the caller can assign\n // groups or suspend over the member's current groups. This keeps out-of-scope\n // users' emails, status, and group shape hidden.\n const canAssignGroups = canPerformMembershipOperation(scope, \"assignGroups\", groupIds)\n const canSuspendScope = canPerformMembershipOperation(scope, \"suspend\", groupIds)\n if (!canAssignGroups && !canSuspendScope) {\n continue\n }\n\n const isSelf = user.id === session.user.id\n members.push({\n user,\n groupIds,\n capabilities: {\n assignGroups: canAssignGroups,\n // A caller cannot suspend themselves; reactivation only applies to a\n // suspended member and never restores sessions.\n suspend: canSuspendScope && !isSelf && user.status === \"active\",\n reactivate: canSuspendScope && user.status === \"suspended\",\n },\n })\n }\n\n const page = paginate(members, { limit, offset })\n return { members: page.page, hasMore: page.hasMore, total: page.total }\n }\n\n async updateMemberGroups(\n request: Request,\n input: UpdateMemberGroupsInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<UpdateMemberGroupsResult> {\n const session = await this.requireUser(request, options)\n const storage = this.requireAuthStorage()\n const scope = this.resolveMembershipPolicyScopeForUser(session.groupIds)\n const userId = assertNonEmpty(input.userId, \"User id\")\n\n // The target must exist and every group it currently holds must be assignable\n // by the caller. Missing and out-of-scope targets raise the same error so a\n // caller cannot probe which users exist.\n const { user, groupIds: currentGroupIds } = await this.requireManageableMember(\n storage,\n scope,\n \"assignGroups\",\n userId\n )\n\n const requestedGroupIds = this.resolveMemberGroupIds(input.groupIds)\n // Every requested group must fall within the caller's assign scope.\n const missing = missingMembershipGroupIds(scope, \"assignGroups\", requestedGroupIds)\n if (missing.length > 0) {\n throw new AuthRuntimeError(\n \"authorization_denied\",\n `[Sixb] The current user is not allowed to assign group(s): ${missing.join(\", \")}.`\n )\n }\n\n const current = new Set(currentGroupIds)\n const requested = new Set(requestedGroupIds)\n const additions = requestedGroupIds.filter((groupId) => !current.has(groupId))\n const removals = currentGroupIds.filter((groupId) => !requested.has(groupId))\n\n // Self-protection: a caller may add in-scope groups to themselves but may not\n // remove any of their own current groups, so they cannot lock themselves out.\n if (user.id === session.user.id && removals.length > 0) {\n throw new AuthRuntimeError(\n \"authorization_denied\",\n \"[Sixb] The current user cannot remove their own groups.\"\n )\n }\n\n const now = new Date()\n for (const groupId of additions) {\n await storage.groupMemberships.upsert({\n projectId: this.projectId,\n userId: user.id,\n groupId,\n source: \"manual\",\n createdAt: now,\n })\n }\n for (const groupId of removals) {\n await storage.groupMemberships.remove({\n projectId: this.projectId,\n userId: user.id,\n groupId,\n })\n }\n\n // The user's cached session carries its old groups; drop it so the next\n // request resolves the updated membership.\n this.invalidateUserSessions(user.id)\n\n const groupIds = (\n await storage.groupMemberships.listForUser({ projectId: this.projectId, userId: user.id })\n ).map((membership) => membership.groupId)\n\n return { user, groupIds }\n }\n\n async suspendMember(\n request: Request,\n input: SuspendMemberInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<SuspendMemberResult> {\n const session = await this.requireUser(request, options)\n const storage = this.requireAuthStorage()\n const scope = this.resolveMembershipPolicyScopeForUser(session.groupIds)\n const userId = assertNonEmpty(input.userId, \"User id\")\n const { user, groupIds } = await this.requireManageableMember(storage, scope, \"suspend\", userId)\n\n if (user.id === session.user.id) {\n throw new AuthRuntimeError(\n \"authorization_denied\",\n \"[Sixb] The current user cannot suspend themselves.\"\n )\n }\n\n const suspended = await storage.suspendUserAndRevokeSessions({\n projectId: this.projectId,\n userId: user.id,\n suspendedAt: new Date(),\n })\n // Storage revoked the user's sessions; drop cached copies so the suspended\n // user stops authenticating immediately.\n this.invalidateUserSessions(user.id)\n\n return { user: suspended, groupIds }\n }\n\n async reactivateMember(\n request: Request,\n input: ReactivateMemberInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<ReactivateMemberResult> {\n const session = await this.requireUser(request, options)\n const storage = this.requireAuthStorage()\n const scope = this.resolveMembershipPolicyScopeForUser(session.groupIds)\n const userId = assertNonEmpty(input.userId, \"User id\")\n const { user, groupIds } = await this.requireManageableMember(storage, scope, \"suspend\", userId)\n\n // Reactivation restores access but not sessions; the user signs in again.\n const reactivated = await storage.users.updateStatus({\n projectId: this.projectId,\n id: user.id,\n status: \"active\",\n updatedAt: new Date(),\n })\n\n return { user: reactivated, groupIds }\n }\n\n /** Drop cached sessions for a user after a membership or status change. */\n invalidateUserSessions(userId: string): void {\n this.sessionCache?.invalidateUser(userId)\n }\n\n private scopedGroupOptions(groupIds: ReadonlySet<string>): InvitationGroupOption[] {\n return this.security\n .listGroups()\n .filter((group) => groupIds.has(group.id))\n .map((group) => ({\n id: group.id,\n ...(group.label !== undefined ? { label: group.label } : {}),\n ...(group.description !== undefined ? { description: group.description } : {}),\n }))\n }\n\n /**\n * Resolve a member the caller may act on for the given operation.\n *\n * A member is manageable only when every group they currently hold is within\n * the caller's scope for that operation (a group-less member is manageable by\n * any holder of the operation). Missing and out-of-scope members raise the same\n * error so callers cannot probe which users exist or how they are grouped.\n */\n private async requireManageableMember(\n storage: AuthStorage,\n scope: MembershipPolicyScope,\n operation: MembershipOperation,\n userId: string\n ): Promise<{ readonly user: UserRecord; readonly groupIds: readonly string[] }> {\n const user = await storage.users.getById({ projectId: this.projectId, id: userId })\n const groupIds = user\n ? (await storage.groupMemberships.listForUser({ projectId: this.projectId, userId })).map(\n (membership) => membership.groupId\n )\n : []\n\n if (!user || !canPerformMembershipOperation(scope, operation, groupIds)) {\n throw new AuthStorageError(\n \"missing_user\",\n `[Sixb] User '${userId}' not found for project '${this.projectId}'.`\n )\n }\n\n return { user, groupIds }\n }\n\n private resolveMemberGroupIds(input: readonly string[]): readonly string[] {\n const groupIds = [...new Set(input.map((groupId) => assertNonEmpty(groupId, \"Group id\")))]\n for (const groupId of groupIds) {\n if (!this.security.getGroupById(groupId)) {\n throw new AuthRuntimeError(\n \"invalid_auth_input\",\n `[Sixb] Unknown group '${groupId}'. Add it to 'security/groups/' or pass it to createSixb({ groups }).`\n )\n }\n }\n return groupIds\n }\n\n async invite(\n request: Request,\n input: InviteUserInput,\n options: InviteUserOptions = {}\n ): Promise<InviteUserResult> {\n const session = await this.requireUser(request, options)\n const authStorage = this.requireAuthStorage()\n const now = new Date()\n const groupIds = this.resolveInviteGroupIds(input)\n this.assertCanManageInvitationGroups(session.groupIds, groupIds)\n\n const strategy = this.getStrategy()\n if (!isInvitationDeliveryAuthStrategy(strategy)) {\n throw new AuthRuntimeError(\n \"invalid_auth_config\",\n \"[Sixb] The active auth strategy does not support invitations.\"\n )\n }\n\n await this.assertCanInviteRecipient(strategy, authStorage, input.email, now)\n const deliveryAudience = resolveAuthSessionAudience(\n options.delivery?.audience ?? options.audience\n )\n this.assertInvitationApplicationAccess(groupIds, deliveryAudience)\n\n const invitation = await authStorage.invitations.createOrUpdateActive({\n id: `inv_${randomUUID()}`,\n projectId: this.projectId,\n email: input.email,\n groupIds,\n createdByPrincipal: session.principal,\n createdBySessionId: session.session.id,\n createdAt: now,\n updatedAt: now,\n expiresAt: resolveInvitationExpiresAt(input.expiresAt, now),\n })\n\n let delivery: InviteDeliveryResult\n try {\n delivery = await strategy.deliverInvitation({\n projectId: this.projectId,\n authStorage,\n invitation,\n audience: deliveryAudience,\n returnTo: options.delivery?.returnTo ?? sanitizeReturnTo(input.returnTo),\n requestOrigin: options.delivery?.requestOrigin ?? new URL(request.url).origin,\n revealLink: input.revealLink,\n now,\n })\n } catch (error) {\n await this.revokeInvitationAfterDeliveryFailure(authStorage, invitation, now)\n throw error\n }\n\n // The runtime owns the disclosure boundary even for third-party strategies. A strategy that\n // accidentally returns a link must not expose it unless the caller opted in explicitly.\n delivery = {\n status: delivery.status,\n ...(input.revealLink && delivery.link ? { link: delivery.link } : {}),\n }\n\n if (delivery.status === \"not_supported\") {\n return { invitation, delivery }\n }\n\n if (delivery.status !== \"sent\") {\n await this.revokeInvitationAfterDeliveryFailure(authStorage, invitation, now)\n throw this.createInvitationDeliveryError(delivery.status)\n }\n\n return { invitation, delivery }\n }\n\n async listInvitations(\n request: Request,\n input: ListInvitationsInput = {},\n options: AuthSessionResolutionOptions = {}\n ): Promise<ListInvitationsResult> {\n const session = await this.requireUser(request, options)\n const authStorage = this.requireAuthStorage()\n const { limit, offset } = normalizePagination(input)\n const result = await authStorage.invitations.list({\n projectId: this.projectId,\n email: input.email,\n statuses: input.statuses,\n order: input.order,\n })\n const scope = this.resolveMembershipPolicyScopeForUser(session.groupIds)\n const manageable = result.invitations.filter((invitation) =>\n canPerformMembershipOperation(scope, \"invite\", invitation.groupIds)\n )\n const page = paginate(manageable, { limit, offset })\n\n return {\n invitations: page.page,\n hasMore: page.hasMore,\n total: page.total,\n }\n }\n\n async revokeInvitation(\n request: Request,\n input: RevokeInvitationInput,\n options: AuthSessionResolutionOptions = {}\n ): Promise<RevokeInvitationResult> {\n const session = await this.requireUser(request, options)\n const authStorage = this.requireAuthStorage()\n const invitationId = assertNonEmpty(input.invitationId, \"Invitation id\")\n const invitation = await authStorage.invitations.getById({\n projectId: this.projectId,\n id: invitationId,\n })\n\n if (!invitation) {\n throw new AuthStorageError(\n \"missing_invitation\",\n `[Sixb] Invitation '${invitationId}' not found for project '${this.projectId}'.`\n )\n }\n\n this.assertCanManageInvitationGroups(session.groupIds, invitation.groupIds)\n\n if (invitation.status !== \"pending\") {\n throw new AuthRuntimeError(\n \"invalid_auth_input\",\n `[Sixb] Invitation '${invitationId}' is already ${invitation.status} and cannot be revoked.`\n )\n }\n\n return {\n invitation: await authStorage.invitations.revoke({\n projectId: this.projectId,\n id: invitation.id,\n revokedAt: new Date(),\n }),\n }\n }\n\n private requireAuthStorage() {\n if (!this.storage.auth) {\n throw new AuthRuntimeError(\n \"auth_storage_missing\",\n \"[Sixb] Auth is enabled but storage.auth is not configured.\"\n )\n }\n\n return this.storage.auth\n }\n\n private resolveInviteGroupIds(input: InviteUserInput): readonly string[] {\n if (input.groups && input.groupIds) {\n throw new AuthRuntimeError(\n \"invalid_auth_input\",\n \"[Sixb] Invitation input cannot provide both groups and groupIds.\"\n )\n }\n\n const rawGroupIds =\n input.groupIds ?? input.groups?.map((group) => assertNonEmpty(group.id, \"Group id\")) ?? []\n const groupIds = [...new Set(rawGroupIds.map((groupId) => assertNonEmpty(groupId, \"Group id\")))]\n\n for (const groupId of groupIds) {\n if (!this.security.getGroupById(groupId)) {\n throw new AuthRuntimeError(\n \"invalid_auth_input\",\n `[Sixb] Unknown invitation group '${groupId}'. Add it to 'security/groups/' or pass it to createSixb({ groups }).`\n )\n }\n }\n\n return groupIds\n }\n\n private resolveMembershipPolicyScopeForUser(callerGroupIds: readonly string[]) {\n return resolveMembershipPolicyScope({\n membershipPolicies: this.security.listMembershipPolicies(),\n callerGroupIds,\n })\n }\n\n private resolveCreateInvitationCapability(input: {\n readonly canInvite: boolean\n }): GetInvitationOptionsResult[\"capabilities\"][\"createInvitation\"] {\n if (!isInvitationDeliveryAuthStrategy(this.getStrategy())) {\n return { state: \"disabled\", reason: \"invitation_delivery_not_supported\" }\n }\n\n if (!input.canInvite) {\n return { state: \"disabled\", reason: \"missing_membership_policy\" }\n }\n\n return { state: \"enabled\" }\n }\n\n private assertInvitationApplicationAccess(\n groupIds: readonly string[],\n audience: AuthSessionAudience\n ): void {\n // Check only the groups this invitation assigns. Existing memberships may\n // be outside the caller's policy scope and must not affect this response.\n const roles = this.security.listResolvedRoles()\n const authorization = resolveAuthorizationContext({\n principal: { type: \"user\", id: \"invited-user\" },\n groupIds,\n roles,\n })\n\n if (canAccessApplication(authorization, roles, audience)) return\n\n throw new AuthRuntimeError(\n \"authorization_denied\",\n `[Sixb] Invitation groups do not grant access to application '${audience}'.`\n )\n }\n\n private async assertCanInviteRecipient(\n strategy: InvitationDeliveryAuthStrategy,\n authStorage: AuthStorage,\n email: string,\n now: Date\n ): Promise<void> {\n if (!strategy.validateInvitationRecipient) {\n return\n }\n\n const result = await strategy.validateInvitationRecipient({\n projectId: this.projectId,\n authStorage,\n email,\n now,\n })\n\n if (result.status === \"allowed\") {\n return\n }\n\n throw createInvitationRecipientError(result.status, result.email ?? email)\n }\n\n private async revokeInvitationAfterDeliveryFailure(\n authStorage: AuthStorage,\n invitation: InvitationRecord,\n failedAt: Date\n ): Promise<void> {\n await authStorage.invitations.revoke({\n projectId: this.projectId,\n id: invitation.id,\n revokedAt: failedAt,\n })\n }\n\n private createInvitationDeliveryError(\n status: Exclude<InviteDeliveryStatus, \"sent\" | \"not_supported\">\n ) {\n if (status === \"rate_limited\") {\n return new AuthRuntimeError(\n \"rate_limited\",\n \"[Sixb] Invitation delivery is rate limited. Try again later.\"\n )\n }\n\n return new AuthRuntimeError(\n \"invalid_auth_input\",\n \"[Sixb] Invitation delivery was skipped by the active auth strategy.\"\n )\n }\n\n private assertCanManageInvitationGroups(\n callerGroupIds: readonly string[],\n groupIds: readonly string[]\n ): void {\n const scope = this.resolveMembershipPolicyScopeForUser(callerGroupIds)\n\n if (canPerformMembershipOperation(scope, \"invite\", groupIds)) {\n return\n }\n\n if (groupIds.length === 0) {\n throw new AuthRuntimeError(\n \"authorization_denied\",\n \"[Sixb] The current user is not allowed to create or manage invitations without groups.\"\n )\n }\n\n const missing = missingMembershipGroupIds(scope, \"invite\", groupIds)\n throw new AuthRuntimeError(\n \"authorization_denied\",\n `[Sixb] The current user is not allowed to create or manage invitations for group(s): ${missing.join(\", \")}.`\n )\n }\n}\n\nfunction resolveCorrelationId(request: Request): string {\n return (\n request.headers.get(\"x-correlation-id\") ?? request.headers.get(\"x-request-id\") ?? randomUUID()\n )\n}\n\nfunction isAuthenticatedUserRequestSession(\n session: AuthenticatedRequestAuthSession\n): session is AuthenticatedUserRequestSession {\n return session.principal.type === \"user\"\n}\n\nfunction resolveRequestIpAddress(request: Request): string | undefined {\n return (\n request.headers.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim() ||\n request.headers.get(\"x-real-ip\")?.trim() ||\n undefined\n )\n}\n\nfunction constrainTokenGroupIds(\n principalGroupIds: readonly string[],\n accessToken: AccessTokenRecord\n): readonly string[] {\n if (accessToken.groupIds === undefined) {\n return principalGroupIds\n }\n\n const allowed = new Set(accessToken.groupIds)\n return principalGroupIds.filter((groupId) => allowed.has(groupId))\n}\n\n// A caller may manage a service account only when it belongs to every group the\n// account is in, so managing it can never grant more than the caller already\n// has. An account with no groups is powerless and therefore freely manageable.\nfunction callerCanManageServiceAccount(\n callerGroupIds: readonly string[],\n serviceAccountGroupIds: readonly string[]\n): boolean {\n const callerGroups = new Set(callerGroupIds)\n return serviceAccountGroupIds.every((groupId) => callerGroups.has(groupId))\n}\n\nfunction missingAccessTokenError(tokenId: string, projectId: string): AuthStorageError {\n return new AuthStorageError(\n \"missing_access_token\",\n `[Sixb] Access token '${tokenId}' not found for project '${projectId}'.`\n )\n}\n\n/**\n * Restrict the groups requested for a credential to a set the caller is allowed\n * to grant. Returns undefined when no groups were requested (an unconstrained\n * credential) and throws when a requested group falls outside the allowed set.\n */\nfunction constrainRequestedGroupIds(\n input: readonly string[] | undefined,\n allowedGroupIds: readonly string[],\n options: { readonly subject: string }\n): readonly string[] | undefined {\n const groupIds = normalizeRequestedGroupIds(input)\n if (!groupIds) {\n return undefined\n }\n\n const allowed = new Set(allowedGroupIds)\n for (const groupId of groupIds) {\n if (!allowed.has(groupId)) {\n throw new AuthRuntimeError(\n \"authorization_denied\",\n `[Sixb] Group '${groupId}' cannot be assigned to this ${options.subject}.`\n )\n }\n }\n\n return groupIds\n}\n\nfunction normalizeRequestedGroupIds(\n input: readonly string[] | undefined\n): readonly string[] | null {\n if (input === undefined) {\n return null\n }\n\n const groupIds: string[] = []\n for (const raw of input) {\n const groupId = raw.trim()\n if (!groupId) {\n throw new AuthRuntimeError(\n \"invalid_auth_input\",\n \"[Sixb] Group ids cannot be empty when creating auth credentials.\"\n )\n }\n if (!groupIds.includes(groupId)) {\n groupIds.push(groupId)\n }\n }\n\n return groupIds\n}\n\nfunction createInvitationRecipientError(\n status: Exclude<InvitationRecipientStatus, \"allowed\">,\n email: string\n): AuthRuntimeError {\n if (status === \"rate_limited\") {\n return new AuthRuntimeError(\n \"rate_limited\",\n \"[Sixb] Invitation delivery is rate limited. Try again later.\"\n )\n }\n\n if (status === \"invalid_email\") {\n return new AuthRuntimeError(\"invalid_auth_input\", \"[Sixb] Invitation email is invalid.\")\n }\n\n if (status === \"disallowed_domain\") {\n return new AuthRuntimeError(\n \"invalid_auth_input\",\n `[Sixb] Invitation email '${email}' is not allowed by the active auth strategy.`\n )\n }\n\n return new AuthRuntimeError(\n \"invalid_auth_input\",\n `[Sixb] Invitation email '${email}' belongs to a suspended user.`\n )\n}\n\n/**\n * The public shape of a resolved membership policy scope.\n *\n * `holds` answers \"does any policy grant this at all\", which is what a UI needs to enable a control;\n * `covers` answers the scoped question for one member. Neither is the authorization decision — the\n * runtime methods add rules on top, which is why the third is named for coverage and not for permission.\n */\nfunction membershipCapabilities(scope: MembershipPolicyScope): MembershipCapabilities {\n return {\n holds: {\n invite: scope.operations.invite.policyIds.length > 0,\n assignGroups: scope.operations.assignGroups.policyIds.length > 0,\n suspend: scope.operations.suspend.policyIds.length > 0,\n },\n assignableGroupIds: [...scope.operations.assignGroups.groupIds],\n covers: (operation, memberGroups) =>\n canPerformMembershipOperation(scope, operation, groupIdsOf(memberGroups)),\n }\n}\n\n/**\n * Normalize the two ways a caller can name a group.\n *\n * Ids come from sessions and stored memberships, definitions come from code. Every entry point that\n * takes `GroupReference` funnels through here, so nothing downstream ever sees a definition where an\n * id belongs.\n */\nfunction groupIdsOf(groups: readonly GroupReference[]): readonly string[] {\n return groups.map((group) => (typeof group === \"string\" ? group : group.id))\n}\n",
|
|
8
|
+
"import type { ApplicationDefinition } from \"./types\"\n\n/** Browser applications that can be protected by role grants. */\nexport const applications = {\n atlas: { kind: \"application\", id: \"atlas\", label: \"Atlas\" },\n app: { kind: \"application\", id: \"app\", label: \"Custom app\" },\n} as const satisfies Readonly<Record<string, ApplicationDefinition>>\n\nexport const APPLICATION_IDS: ReadonlySet<string> = new Set(\n Object.values(applications).map((application) => application.id)\n)\n",
|
|
9
|
+
"export class SecurityValidationError extends Error {\n readonly name = \"SecurityValidationError\"\n}\n",
|
|
10
|
+
"import type { MembershipOperation, MembershipPolicyDefinition } from \"./types\"\n\nexport interface MembershipOperationScope {\n readonly policyIds: readonly string[]\n readonly groupIds: ReadonlySet<string>\n}\n\nexport interface MembershipPolicyScope {\n readonly policyIds: readonly string[]\n readonly operations: Readonly<Record<MembershipOperation, MembershipOperationScope>>\n}\n\nconst MEMBERSHIP_OPERATIONS = [\"invite\", \"assignGroups\", \"suspend\"] as const\n\nexport function resolveMembershipPolicyScope(input: {\n readonly membershipPolicies: readonly MembershipPolicyDefinition[]\n readonly callerGroupIds: readonly string[]\n}): MembershipPolicyScope {\n const callerGroups = new Set(input.callerGroupIds)\n const policyIds: string[] = []\n const operations = createEmptyOperationScopes()\n\n for (const policy of input.membershipPolicies) {\n if (!policy.grantedToGroupIds.some((groupId) => callerGroups.has(groupId))) {\n continue\n }\n\n policyIds.push(policy.id)\n for (const operation of policy.can) {\n operations[operation].policyIds.push(policy.id)\n for (const groupId of policy.scopeGroupIds) {\n operations[operation].groupIds.add(groupId)\n }\n }\n }\n\n return {\n policyIds,\n operations: {\n invite: freezeOperationScope(operations.invite),\n assignGroups: freezeOperationScope(operations.assignGroups),\n suspend: freezeOperationScope(operations.suspend),\n },\n }\n}\n\nexport function canPerformMembershipOperation(\n scope: MembershipPolicyScope,\n operation: MembershipOperation,\n groupIds: readonly string[]\n): boolean {\n const operationScope = scope.operations[operation]\n\n if (operationScope.policyIds.length === 0) {\n return false\n }\n\n if (groupIds.length === 0) {\n return true\n }\n\n return groupIds.every((groupId) => operationScope.groupIds.has(groupId))\n}\n\nexport function missingMembershipGroupIds(\n scope: MembershipPolicyScope,\n operation: MembershipOperation,\n groupIds: readonly string[]\n): readonly string[] {\n if (groupIds.length === 0) {\n return []\n }\n\n const operationScope = scope.operations[operation]\n return groupIds.filter((groupId) => !operationScope.groupIds.has(groupId))\n}\n\nfunction createEmptyOperationScopes(): Record<\n MembershipOperation,\n { policyIds: string[]; groupIds: Set<string> }\n> {\n return {\n invite: { policyIds: [], groupIds: new Set<string>() },\n assignGroups: { policyIds: [], groupIds: new Set<string>() },\n suspend: { policyIds: [], groupIds: new Set<string>() },\n }\n}\n\nfunction freezeOperationScope(input: {\n readonly policyIds: readonly string[]\n readonly groupIds: ReadonlySet<string>\n}): MembershipOperationScope {\n return {\n policyIds: [...input.policyIds],\n groupIds: new Set(input.groupIds),\n }\n}\n\nexport function isMembershipOperation(value: unknown): value is MembershipOperation {\n return MEMBERSHIP_OPERATIONS.includes(value as MembershipOperation)\n}\n",
|
|
11
|
+
"import { GRANT_KINDS, type GrantUniverseKey, grantKindOf } from \"../authorization/grant-kinds\"\nimport { SecurityValidationError } from \"./errors\"\nimport { isMembershipOperation } from \"./membership-policies\"\nimport type {\n GrantCapability,\n GrantDefinition,\n GroupDefinition,\n MembershipPolicyDefinition,\n RegisteredSecurityDefinitions,\n RoleDefinition,\n Selection,\n} from \"./types\"\n\n/** Registered id universes and singleton capabilities available to role grants. */\ntype RegisteredUniverses = Partial<Record<GrantUniverseKey, ReadonlySet<string>>> & {\n readonly agentAvailable?: boolean\n}\n\n/**\n * Every grant capability, for validating grants that arrive from untyped code.\n *\n * Written as a total `Record<GrantCapability, true>` rather than a bare array so a capability added\n * to `GrantDefinition` is a compile error here — the same discipline `GRANT_KINDS` uses. The\n * hand-written `capability !== \"access\" && …` chain this replaces would have accepted the new\n * capability at startup and then died on `GRANT_KINDS[kind].universeKey`.\n */\nconst GRANT_CAPABILITIES = Object.keys({\n access: true,\n view: true,\n edit: true,\n append: true,\n apply: true,\n run: true,\n observe: true,\n manage: true,\n} satisfies Record<GrantCapability, true>) as readonly GrantCapability[]\n\n/** \"'a', 'b', or 'c'\" — the shape the security errors already use. */\nfunction formatAlternatives(values: readonly string[]): string {\n const quoted = values.map((value) => `'${value}'`)\n const last = quoted.at(-1)\n return quoted.length < 2 ? (last ?? \"\") : `${quoted.slice(0, -1).join(\", \")}, or ${last}`\n}\n\nexport type CreateSecurityError = (message: string) => Error\n\n// Shared, single-source validation primitives. The builders reuse these too, so\n// authoring-time and startup-time checks can never drift apart.\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nexport function assertNonEmptyString(\n value: unknown,\n field: string,\n createError: CreateSecurityError = (message) => new SecurityValidationError(message)\n): asserts value is string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw createError(`[Sixb] ${field} must not be empty.`)\n }\n}\n\nexport function assertOptionalString(\n value: unknown,\n field: string,\n createError: CreateSecurityError = (message) => new SecurityValidationError(message)\n): asserts value is string | undefined {\n if (value === undefined) {\n return\n }\n\n if (typeof value !== \"string\") {\n throw createError(`[Sixb] ${field} must be a string.`)\n }\n}\n\nfunction assertStringArray(\n value: unknown,\n field: string,\n createError: CreateSecurityError\n): asserts value is readonly string[] {\n if (!Array.isArray(value)) {\n throw createError(`[Sixb] ${field} must be an array of group ids.`)\n }\n\n for (const item of value) {\n assertNonEmptyString(item, `${field} item`, createError)\n }\n}\n\nfunction assertMembershipOperationArray(\n value: unknown,\n field: string,\n createError: CreateSecurityError\n): asserts value is MembershipPolicyDefinition[\"can\"] {\n if (!Array.isArray(value)) {\n throw createError(`[Sixb] ${field} must be an array of membership operations.`)\n }\n\n for (const item of value) {\n if (!isMembershipOperation(item)) {\n throw createError(\n `[Sixb] ${field} must contain only membership operations: invite, assignGroups, suspend.`\n )\n }\n }\n}\n\nfunction assertNoDuplicateIds(ids: readonly string[], field: string): void {\n const seen = new Set<string>()\n for (const id of ids) {\n if (seen.has(id)) {\n throw new SecurityValidationError(`[Sixb] ${field} contains duplicate group id '${id}'.`)\n }\n seen.add(id)\n }\n}\n\nfunction assertNoDuplicateOperations(\n operations: readonly MembershipPolicyDefinition[\"can\"][number][],\n field: string\n): void {\n const seen = new Set<string>()\n for (const operation of operations) {\n if (seen.has(operation)) {\n throw new SecurityValidationError(\n `[Sixb] ${field} contains duplicate operation '${operation}'.`\n )\n }\n seen.add(operation)\n }\n}\n\nexport function assertGroupDefinition(\n value: unknown,\n createError: CreateSecurityError = (message) => new SecurityValidationError(message)\n): asserts value is GroupDefinition {\n if (!isRecord(value)) {\n throw createError(\"[Sixb] Group definition must be an object.\")\n }\n\n if (value.kind !== \"group\") {\n throw createError(\"[Sixb] Group definition kind must be 'group'.\")\n }\n\n assertNonEmptyString(value.id, \"Group id\", createError)\n assertOptionalString(value.label, `Group '${value.id}' label`, createError)\n assertOptionalString(value.description, `Group '${value.id}' description`, createError)\n}\n\nexport function isGroupDefinition(value: unknown): value is GroupDefinition {\n try {\n assertGroupDefinition(value, (message) => new Error(message))\n return true\n } catch {\n return false\n }\n}\n\nexport function assertMembershipPolicyDefinition(\n value: unknown,\n createError: CreateSecurityError = (message) => new SecurityValidationError(message)\n): asserts value is MembershipPolicyDefinition {\n if (!isRecord(value)) {\n throw createError(\"[Sixb] Membership policy definition must be an object.\")\n }\n\n if (value.kind !== \"membershipPolicy\") {\n throw createError(\"[Sixb] Membership policy definition kind must be 'membershipPolicy'.\")\n }\n\n assertNonEmptyString(value.id, \"Membership policy id\", createError)\n assertStringArray(\n value.grantedToGroupIds,\n `Membership policy '${value.id}' grantedTo`,\n createError\n )\n assertStringArray(value.scopeGroupIds, `Membership policy '${value.id}' scope`, createError)\n assertMembershipOperationArray(value.can, `Membership policy '${value.id}' can`, createError)\n}\n\nexport function isMembershipPolicyDefinition(value: unknown): value is MembershipPolicyDefinition {\n try {\n assertMembershipPolicyDefinition(value, (message) => new Error(message))\n return true\n } catch {\n return false\n }\n}\n\nexport function assertGrantDefinition(\n value: unknown,\n field: string,\n createError: CreateSecurityError = (message) => new SecurityValidationError(message)\n): asserts value is GrantDefinition {\n if (!isRecord(value) || value.kind !== \"grant\") {\n throw createError(`[Sixb] ${field} must contain only grant definitions from 'can'.`)\n }\n\n if (!GRANT_CAPABILITIES.includes(value.capability as GrantCapability)) {\n throw createError(\n `[Sixb] ${field} grant capability must be ${formatAlternatives(GRANT_CAPABILITIES)}.`\n )\n }\n\n if (value.capability === \"access\" && value.target !== \"application\") {\n throw createError(`[Sixb] ${field} access grant target must be 'application'.`)\n }\n\n if (value.capability === \"view\" && value.target !== \"object\" && value.target !== \"dataset\") {\n throw createError(`[Sixb] ${field} view grant target must be 'object' or 'dataset'.`)\n }\n\n if (\n value.capability === \"run\" &&\n value.target !== \"workflow\" &&\n value.target !== \"sync\" &&\n value.target !== \"pipeline\" &&\n value.target !== \"agent\"\n ) {\n throw createError(\n `[Sixb] ${field} run grant target must be 'workflow', 'sync', 'pipeline', or 'agent'.`\n )\n }\n\n if (value.capability === \"observe\" && value.target !== \"logs\" && value.target !== \"aiUsage\") {\n throw createError(`[Sixb] ${field} observe grant target must be 'logs' or 'aiUsage'.`)\n }\n\n if (value.capability === \"manage\" && value.target !== \"connector\" && value.target !== \"aiUsage\") {\n throw createError(`[Sixb] ${field} manage grant target must be 'connector' or 'aiUsage'.`)\n }\n\n if (value.capability === \"run\" && value.target === \"agent\") {\n if (value.selection !== undefined) {\n throw createError(`[Sixb] ${field} agent run grant must not declare a selection.`)\n }\n return\n }\n\n assertSelection(value.selection, field, createError)\n}\n\nfunction assertSelection(\n value: unknown,\n field: string,\n createError: CreateSecurityError\n): asserts value is Selection {\n if (!isRecord(value) || typeof value.all !== \"boolean\") {\n throw createError(`[Sixb] ${field} grant must carry a selection from 'can' or a scope.`)\n }\n\n const ids = value.all ? value.except : value.ids\n if (!Array.isArray(ids)) {\n throw createError(`[Sixb] ${field} grant selection must list ids.`)\n }\n\n for (const id of ids) {\n assertNonEmptyString(id, `${field} grant selection id`, createError)\n }\n}\n\nexport function assertRoleDefinition(\n value: unknown,\n createError: CreateSecurityError = (message) => new SecurityValidationError(message)\n): asserts value is RoleDefinition {\n if (!isRecord(value)) {\n throw createError(\"[Sixb] Role definition must be an object.\")\n }\n\n if (value.kind !== \"role\") {\n throw createError(\"[Sixb] Role definition kind must be 'role'.\")\n }\n\n assertNonEmptyString(value.id, \"Role id\", createError)\n assertOptionalString(value.label, `Role '${value.id}' label`, createError)\n assertOptionalString(value.description, `Role '${value.id}' description`, createError)\n assertStringArray(value.grantedToGroupIds, `Role '${value.id}' grantedTo`, createError)\n\n if (!Array.isArray(value.grants)) {\n throw createError(`[Sixb] Role '${value.id}' grants must be an array.`)\n }\n\n for (const grant of value.grants) {\n assertGrantDefinition(grant, `Role '${value.id}' grants`, createError)\n }\n}\n\nexport function isRoleDefinition(value: unknown): value is RoleDefinition {\n try {\n assertRoleDefinition(value, (message) => new Error(message))\n return true\n } catch {\n return false\n }\n}\n\nexport function validateSecurityDefinitionsAtStartup(input: {\n readonly groups: readonly GroupDefinition[]\n readonly membershipPolicies: readonly MembershipPolicyDefinition[]\n readonly roles?: readonly RoleDefinition[]\n /** Registered browser application ids — when provided, access grants must reference them. */\n readonly applicationIds?: ReadonlySet<string>\n /** Registered object type ids — when provided, view grants must reference them. */\n readonly objectTypeIds?: ReadonlySet<string>\n /** Registered dataset ids — when provided, dataset view grants must reference them. */\n readonly datasetIds?: ReadonlySet<string>\n /** Registered action ids — when provided, apply grants must reference them. */\n readonly actionIds?: ReadonlySet<string>\n /** Registered workflow ids — when provided, run grants must reference them. */\n readonly workflowIds?: ReadonlySet<string>\n /** Registered sync ids — when provided, sync run grants must reference them. */\n readonly syncIds?: ReadonlySet<string>\n /** Registered pipeline ids — when provided, pipeline run grants must reference them. */\n readonly pipelineIds?: ReadonlySet<string>\n /** Whether the project's single conversational Agent is configured. */\n readonly agentAvailable?: boolean\n /** Registered observability surfaces. */\n readonly observableIds?: ReadonlySet<string>\n /** Registered singleton management surfaces. */\n readonly manageableIds?: ReadonlySet<string>\n /** Registered connector ids — when provided, manage grants must reference them. */\n readonly connectorIds?: ReadonlySet<string>\n}): RegisteredSecurityDefinitions {\n const groupsById = new Map<string, GroupDefinition>()\n const rolesById = new Map<string, RoleDefinition>()\n const membershipPoliciesById = new Map<string, MembershipPolicyDefinition>()\n\n for (const group of input.groups) {\n assertGroupDefinition(group)\n\n if (groupsById.has(group.id)) {\n throw new SecurityValidationError(`[Sixb] Duplicate group id: ${group.id}`)\n }\n\n groupsById.set(group.id, group)\n }\n\n for (const role of input.roles ?? []) {\n assertRoleDefinition(role)\n\n if (rolesById.has(role.id)) {\n throw new SecurityValidationError(`[Sixb] Duplicate role id: ${role.id}`)\n }\n\n if (role.grantedToGroupIds.length === 0) {\n throw new SecurityValidationError(\n `[Sixb] Role '${role.id}' must be granted to at least one group.`\n )\n }\n\n if (role.grants.length === 0) {\n throw new SecurityValidationError(`[Sixb] Role '${role.id}' must declare at least one grant.`)\n }\n\n assertNoDuplicateIds(role.grantedToGroupIds, `Role '${role.id}' grantedTo`)\n\n for (const groupId of role.grantedToGroupIds) {\n if (!groupsById.has(groupId)) {\n throw new SecurityValidationError(\n `[Sixb] Role '${role.id}' grantedTo references unknown group '${groupId}'. Add it to 'security/groups/' or pass it to createSixb({ groups }).`\n )\n }\n }\n\n for (const grant of role.grants) {\n assertGrantReferences(role.id, grant, input)\n }\n\n rolesById.set(role.id, role)\n }\n\n for (const policy of input.membershipPolicies) {\n assertMembershipPolicyDefinition(policy)\n\n if (membershipPoliciesById.has(policy.id)) {\n throw new SecurityValidationError(`[Sixb] Duplicate membership policy id: ${policy.id}`)\n }\n\n if (policy.grantedToGroupIds.length === 0) {\n throw new SecurityValidationError(\n `[Sixb] Membership policy '${policy.id}' must grant membership authority to at least one group.`\n )\n }\n\n if (policy.can.length === 0) {\n throw new SecurityValidationError(\n `[Sixb] Membership policy '${policy.id}' must declare at least one operation.`\n )\n }\n\n assertNoDuplicateIds(policy.grantedToGroupIds, `Membership policy '${policy.id}' grantedTo`)\n assertNoDuplicateIds(policy.scopeGroupIds, `Membership policy '${policy.id}' scope`)\n assertNoDuplicateOperations(policy.can, `Membership policy '${policy.id}' can`)\n\n for (const groupId of policy.grantedToGroupIds) {\n if (!groupsById.has(groupId)) {\n throw new SecurityValidationError(\n `[Sixb] Membership policy '${policy.id}' grantedTo references unknown group '${groupId}'. Add it to 'security/groups/' or pass it to createSixb({ groups }).`\n )\n }\n }\n\n for (const groupId of policy.scopeGroupIds) {\n if (!groupsById.has(groupId)) {\n throw new SecurityValidationError(\n `[Sixb] Membership policy '${policy.id}' scope references unknown group '${groupId}'. Add it to 'security/groups/' or pass it to createSixb({ groups }).`\n )\n }\n }\n\n membershipPoliciesById.set(policy.id, policy)\n }\n\n return {\n groups: [...groupsById.values()],\n groupsById,\n roles: [...rolesById.values()],\n rolesById,\n membershipPolicies: [...membershipPoliciesById.values()],\n membershipPoliciesById,\n }\n}\n\nfunction assertGrantReferences(\n roleId: string,\n grant: GrantDefinition,\n registered: RegisteredUniverses\n): void {\n if (grant.capability === \"run\" && grant.target === \"agent\") {\n const spec = GRANT_KINDS[grantKindOf(grant)]\n if (!registered.agentAvailable) {\n throw new SecurityValidationError(\n `[Sixb] Role '${roleId}' grants ${grant.capability} on the project Agent, but it is unavailable. ${spec.fix}`\n )\n }\n return\n }\n const spec = GRANT_KINDS[grantKindOf(grant)]\n const universe = registered[spec.universeKey]\n\n if (!universe) {\n return\n }\n\n // Explicit selections list ids to include; \"all except\" selections list ids\n // to exclude. Either way every named id must be registered — an unknown id is\n // a typo that would silently widen or no-op the grant.\n const ids = grant.selection.all ? grant.selection.except : grant.selection.ids\n\n for (const id of ids) {\n if (!universe.has(id)) {\n throw new SecurityValidationError(\n `[Sixb] Role '${roleId}' grants ${grant.capability} on unknown ${spec.subject} '${id}'. ${spec.fix}`\n )\n }\n }\n}\n",
|
|
12
|
+
"import { SecurityValidationError } from \"./errors\"\nimport type {\n GrantDefinition,\n GroupDefinition,\n MembershipOperation,\n MembershipPolicyDefinition,\n RoleDefinition,\n} from \"./types\"\nimport {\n assertGrantDefinition,\n assertNonEmptyString,\n assertOptionalString,\n isRecord,\n} from \"./validation\"\n\nexport interface DefineGroupOptions {\n readonly label?: string\n readonly description?: string\n}\n\nexport interface DefineRoleOptions {\n readonly label?: string\n readonly description?: string\n readonly grantedTo: readonly GroupDefinition[]\n readonly grants: readonly GrantDefinition[]\n}\n\nexport interface DefineMembershipPolicyOptions {\n readonly grantedTo: readonly GroupDefinition[]\n readonly scope: readonly GroupDefinition[]\n readonly can: readonly MembershipOperation[]\n}\n\nconst MEMBERSHIP_OPERATIONS = new Set<MembershipOperation>([\"invite\", \"assignGroups\", \"suspend\"])\n\nfunction assertNonEmptyArray<T>(value: readonly T[], field: string): void {\n if (value.length === 0) {\n throw new SecurityValidationError(`[Sixb] ${field} must not be empty.`)\n }\n}\n\nfunction groupIdsFrom(groups: readonly GroupDefinition[], field: string): readonly string[] {\n return groups.map((group) => {\n if (!isRecord(group) || group.kind !== \"group\") {\n throw new SecurityValidationError(`[Sixb] ${field} must contain only group definitions.`)\n }\n\n assertNonEmptyString(group.id, `${field} group id`)\n return group.id\n })\n}\n\nfunction membershipOperationsFrom(\n operations: readonly MembershipOperation[],\n field: string\n): readonly MembershipOperation[] {\n return operations.map((operation) => {\n if (!MEMBERSHIP_OPERATIONS.has(operation)) {\n throw new SecurityValidationError(\n `[Sixb] ${field} must contain only membership operations: invite, assignGroups, suspend.`\n )\n }\n\n return operation\n })\n}\n\nexport function defineGroup<const TId extends string>(\n id: TId,\n options: DefineGroupOptions = {}\n): GroupDefinition<TId> {\n assertNonEmptyString(id, \"Group id\")\n assertOptionalString(options.label, `Group '${id}' label`)\n assertOptionalString(options.description, `Group '${id}' description`)\n\n return {\n kind: \"group\",\n id,\n ...(options.label !== undefined ? { label: options.label } : {}),\n ...(options.description !== undefined ? { description: options.description } : {}),\n }\n}\n\nexport function defineRole<const TId extends string>(\n id: TId,\n options: DefineRoleOptions\n): RoleDefinition<TId> {\n assertNonEmptyString(id, \"Role id\")\n assertOptionalString(options.label, `Role '${id}' label`)\n assertOptionalString(options.description, `Role '${id}' description`)\n assertNonEmptyArray(options.grantedTo, `Role '${id}' grantedTo`)\n\n const grantedToGroupIds = groupIdsFrom(options.grantedTo, `Role '${id}' grantedTo`)\n\n for (const grant of options.grants) {\n assertGrantDefinition(grant, `Role '${id}' grants`)\n }\n\n if (options.grants.length === 0) {\n throw new SecurityValidationError(`[Sixb] Role '${id}' grants must not be empty.`)\n }\n\n return {\n kind: \"role\",\n id,\n ...(options.label !== undefined ? { label: options.label } : {}),\n ...(options.description !== undefined ? { description: options.description } : {}),\n grantedToGroupIds,\n grants: options.grants,\n }\n}\n\nexport function defineMembershipPolicy<const TId extends string>(\n id: TId,\n options: DefineMembershipPolicyOptions\n): MembershipPolicyDefinition<TId> {\n assertNonEmptyString(id, \"Membership policy id\")\n assertNonEmptyArray(options.grantedTo, `Membership policy '${id}' grantedTo`)\n assertNonEmptyArray(options.can, `Membership policy '${id}' can`)\n\n return {\n kind: \"membershipPolicy\",\n id,\n grantedToGroupIds: groupIdsFrom(options.grantedTo, `Membership policy '${id}' grantedTo`),\n scopeGroupIds: groupIdsFrom(options.scope, `Membership policy '${id}' scope`),\n can: membershipOperationsFrom(options.can, `Membership policy '${id}' can`),\n }\n}\n",
|
|
13
|
+
"/**\n * Breadth selectors for role grants.\n *\n * `every.object()`, `every.action()`, and friends select a capability's whole registered universe;\n * `.except([...])` removes specific definitions. They are plain data carrying no enforcement logic —\n * `can.view/apply/run/access` turn them into grants, and the authorization engine expands them to\n * concrete id sets at startup (after applying `except`).\n *\n * They live under one `every` namespace on purpose. Spending seven of the best identifiers in\n * `@sixb/core` — `actions`, `workflows`, `syncs`, … — on an auxiliary subsystem collided with the\n * primitives themselves and with `events.actions()` / `logs.actions()` on the client.\n */\n\nimport type { ActionDefinition } from \"../actions/types\"\nimport type { ConnectorDefinition } from \"../connectors\"\nimport type { DatasetDefinition } from \"../datasets\"\nimport type { ObjectType } from \"../ontology\"\nimport type { PipelineDefinition } from \"../pipelines\"\nimport type { SyncDefinition } from \"../syncs\"\nimport type { WorkflowDefinition } from \"../workflows/types\"\nimport { SecurityValidationError } from \"./errors\"\nimport type { ApplicationDefinition } from \"./types\"\n\n/** Capability targets a breadth selector can range over. */\nexport const BREADTH_TARGETS = [\n \"object\",\n \"dataset\",\n \"action\",\n \"workflow\",\n \"sync\",\n \"pipeline\",\n \"application\",\n \"connector\",\n] as const\n\nexport type BreadthTarget = (typeof BREADTH_TARGETS)[number]\n\ninterface BreadthTargetInput {\n object: ObjectType\n dataset: DatasetDefinition\n action: ActionDefinition\n workflow: WorkflowDefinition\n sync: SyncDefinition\n pipeline: PipelineDefinition\n application: ApplicationDefinition\n connector: ConnectorDefinition\n}\n\n/**\n * An \"all except\" selection over a capability target. Branded by `target` so\n * `can.view(every.action())` fails to typecheck.\n */\nexport interface BreadthSelector<TTarget extends BreadthTarget = BreadthTarget> {\n readonly target: TTarget\n readonly selection: { readonly all: true; readonly except: readonly string[] }\n /** Exclude specific definitions from an otherwise-complete selection. */\n except(items: readonly BreadthTargetInput[TTarget][]): BreadthSelector<TTarget>\n}\n\nexport function isBreadthSelector(value: unknown): value is BreadthSelector {\n if (typeof value !== \"object\" || value === null) return false\n const candidate = value as { target?: unknown; selection?: { all?: unknown } }\n return (\n typeof candidate.target === \"string\" &&\n (BREADTH_TARGETS as readonly string[]).includes(candidate.target) &&\n candidate.selection?.all === true\n )\n}\n\nexport function definitionIdOf(item: { readonly id?: unknown }, label: string): string {\n if (typeof item?.id !== \"string\" || !item.id.trim()) {\n throw new SecurityValidationError(`[Sixb] ${label} requires definitions with a non-empty id.`)\n }\n return item.id\n}\n\nfunction all<TTarget extends BreadthTarget>(\n target: TTarget,\n except: readonly string[] = []\n): BreadthSelector<TTarget> {\n return {\n target,\n selection: { all: true, except },\n except(items) {\n return all(target, [\n ...except,\n ...items.map((item) => definitionIdOf(item, `every.${target}() except`)),\n ])\n },\n }\n}\n\n/**\n * The whole registered universe of one capability target.\n *\n * Singular by design: `every.action()` reads as a breadth, where `every.actions()` would just echo\n * the primitive's plural name back.\n */\nexport const every = {\n object: (): BreadthSelector<\"object\"> => all(\"object\"),\n dataset: (): BreadthSelector<\"dataset\"> => all(\"dataset\"),\n action: (): BreadthSelector<\"action\"> => all(\"action\"),\n workflow: (): BreadthSelector<\"workflow\"> => all(\"workflow\"),\n sync: (): BreadthSelector<\"sync\"> => all(\"sync\"),\n pipeline: (): BreadthSelector<\"pipeline\"> => all(\"pipeline\"),\n application: (): BreadthSelector<\"application\"> => all(\"application\"),\n connector: (): BreadthSelector<\"connector\"> => all(\"connector\"),\n}\n",
|
|
14
|
+
"/**\n * Grant builders for role definitions.\n *\n * Grants are plain data referencing application and runtime definitions\n * by id. They carry no enforcement logic — the authorization engine expands\n * each grant's selection into per-principal id sets at startup, so runtime\n * checks stay simple `set.has(id)` lookups.\n */\n\nimport type { ActionDefinition } from \"../actions/types\"\nimport type { AgentReference, AgentUsageReference } from \"../agents/types\"\nimport type { ConnectorDefinition } from \"../connectors\"\nimport type { DatasetDefinition } from \"../datasets\"\nimport type { ObjectType } from \"../ontology\"\nimport type { PipelineDefinition } from \"../pipelines\"\nimport type { SyncDefinition } from \"../syncs\"\nimport type { WorkflowDefinition } from \"../workflows/types\"\nimport { SecurityValidationError } from \"./errors\"\nimport {\n type BreadthSelector,\n type BreadthTarget,\n definitionIdOf,\n isBreadthSelector,\n} from \"./every\"\nimport type {\n AccessGrant,\n AgentRunGrant,\n AppendGrant,\n ApplicationDefinition,\n ApplyGrant,\n EditGrant,\n ManageGrant,\n ObserveGrant,\n RunGrant,\n Selection,\n ViewGrant,\n} from \"./types\"\n\ntype GrantInput<TDefinition, TTarget extends BreadthTarget> =\n | TDefinition\n | readonly TDefinition[]\n | BreadthSelector<TTarget>\n\nconst VIEW_TARGETS = [\"object\", \"dataset\"] as const\nconst RUN_TARGETS = [\"workflow\", \"sync\", \"pipeline\"] as const\n\n/**\n * Seven of the nine targets carry a `kind` discriminant naming themselves. The other two — an\n * `ObjectType` and an `ActionDefinition` — carry none, and each appears in exactly one builder that\n * allows no other undiscriminated target, so the allowed set names them unambiguously.\n */\nconst TARGET_BY_DEFINITION_KIND: Readonly<Partial<Record<string, BreadthTarget>>> = {\n dataset: \"dataset\",\n sync: \"sync\",\n pipeline: \"pipeline\",\n workflow: \"workflow\",\n application: \"application\",\n connector: \"connector\",\n}\n\nconst UNDISCRIMINATED_TARGETS: readonly BreadthTarget[] = [\"object\", \"action\"]\n\nfunction targetOfDefinition<TTarget extends BreadthTarget>(\n item: unknown,\n label: string,\n allowedTargets: readonly TTarget[]\n): TTarget {\n const kind = (item as { readonly kind?: unknown } | null)?.kind\n const discriminated = typeof kind === \"string\" ? TARGET_BY_DEFINITION_KIND[kind] : undefined\n // Recognising the kind is not the same as accepting it. `can.run(myDataset)` used to return\n // `target: \"dataset\"`, and `GRANT_KINDS[\"run:dataset\"]` does not exist, so startup died on\n // `spec.universeKey` with a `TypeError` naming neither the role nor the definition.\n if (discriminated) {\n if (!isAllowedTarget(discriminated, allowedTargets)) {\n // \"one targeting x\", not \"a x definition\": four of the eight targets start with a vowel, and\n // this string ships in a release. Same reason the selector branch below writes no article.\n throw new SecurityValidationError(\n `[Sixb] ${label} accepts ${allowedTargets.join(\" or \")} definitions, but received one targeting ${discriminated}.`\n )\n }\n return discriminated\n }\n\n const candidates = allowedTargets.filter((target) => UNDISCRIMINATED_TARGETS.includes(target))\n const only = candidates.length === 1 ? candidates[0] : undefined\n if (only) return only\n\n throw new SecurityValidationError(\n `[Sixb] ${label} accepts ${allowedTargets.join(\" or \")} definitions, but received one Sixb could not classify.`\n )\n}\n\nfunction isAllowedTarget<TTarget extends BreadthTarget>(\n target: BreadthTarget,\n allowedTargets: readonly TTarget[]\n): target is TTarget {\n return (allowedTargets as readonly BreadthTarget[]).includes(target)\n}\n\n/**\n * Every grant resolves its target and selection here, in one pass, so the two cannot disagree.\n *\n * Typing alone is not enough: a JavaScript caller, or an `as any`, would otherwise hand `can.apply`\n * an `every.object()` and get a grant over the wrong universe. Sniffing only the first element of a\n * list was not enough either — `can.run([mySync, myPipeline])` filed the pipeline's id under\n * `run:sync`, and startup validation then reported it as an unknown *sync*.\n *\n * `TTarget` is what removes the casts at the call sites: each builder passes its own allowed targets\n * and gets exactly those back, so the narrowing is proved rather than asserted.\n */\nfunction resolveGrant<TDefinition extends { readonly id?: unknown }, TTarget extends BreadthTarget>(\n input: GrantInput<TDefinition, TTarget>,\n label: string,\n allowedTargets: readonly TTarget[]\n): { readonly target: TTarget; readonly selection: Selection } {\n if (isBreadthSelector(input)) {\n if (!isAllowedTarget(input.target, allowedTargets)) {\n throw new SecurityValidationError(\n `[Sixb] ${label} accepts ${allowedTargets.join(\" or \")} selectors, but received every.${input.target}().`\n )\n }\n return { target: input.target, selection: input.selection }\n }\n\n const items = Array.isArray(input) ? input : [input as TDefinition]\n\n let target: TTarget | undefined\n for (const item of items) {\n const itemTarget = targetOfDefinition(item, label, allowedTargets)\n if (target === undefined) {\n target = itemTarget\n continue\n }\n if (itemTarget !== target) {\n throw new SecurityValidationError(\n `[Sixb] ${label} requires one target per grant, but received both ${target} and ${itemTarget} definitions. Use one grant each.`\n )\n }\n }\n // Checked after the loop rather than before it: an empty list leaves `target` unset, which is the\n // same condition, and proving it here is what lets the return type stay cast-free.\n if (target === undefined) {\n throw new SecurityValidationError(`[Sixb] ${label} requires at least one definition.`)\n }\n\n // Dedupe explicit ids up front; resolution would dedupe via Set anyway.\n const ids = [...new Set(items.map((item) => definitionIdOf(item, label)))]\n return { target, selection: { all: false, ids } }\n}\n\nfunction access(input: GrantInput<ApplicationDefinition, \"application\">): AccessGrant {\n const { selection } = resolveGrant(input, \"can.access\", [\"application\"])\n return { kind: \"grant\", capability: \"access\", target: \"application\", selection }\n}\n\nfunction view(input: GrantInput<ObjectType, \"object\">): ViewGrant<\"object\">\nfunction view(input: GrantInput<DatasetDefinition, \"dataset\">): ViewGrant<\"dataset\">\nfunction view(input: GrantInput<ObjectType | DatasetDefinition, \"object\" | \"dataset\">): ViewGrant {\n const { target, selection } = resolveGrant(input, \"can.view\", VIEW_TARGETS)\n return { kind: \"grant\", capability: \"view\", target, selection }\n}\n\nfunction edit(input: GrantInput<ObjectType, \"object\">): EditGrant {\n return {\n kind: \"grant\",\n capability: \"edit\",\n selection: resolveGrant(input, \"can.edit\", [\"object\"]).selection,\n }\n}\n\nfunction append(input: GrantInput<ObjectType, \"object\">): AppendGrant {\n return {\n kind: \"grant\",\n capability: \"append\",\n selection: resolveGrant(input, \"can.append\", [\"object\"]).selection,\n }\n}\n\nfunction apply(input: GrantInput<ActionDefinition, \"action\">): ApplyGrant {\n return {\n kind: \"grant\",\n capability: \"apply\",\n selection: resolveGrant(input, \"can.apply\", [\"action\"]).selection,\n }\n}\n\nfunction run(input: GrantInput<WorkflowDefinition, \"workflow\">): RunGrant<\"workflow\">\nfunction run(input: GrantInput<SyncDefinition, \"sync\">): RunGrant<\"sync\">\nfunction run(input: GrantInput<PipelineDefinition, \"pipeline\">): RunGrant<\"pipeline\">\nfunction run(input: AgentReference): AgentRunGrant\nfunction run(\n input:\n | AgentReference\n | GrantInput<\n WorkflowDefinition | SyncDefinition | PipelineDefinition,\n \"workflow\" | \"sync\" | \"pipeline\"\n >\n): RunGrant | AgentRunGrant {\n if (isAgentReference(input)) {\n return { kind: \"grant\", capability: \"run\", target: \"agent\" }\n }\n const { target, selection } = resolveGrant(input, \"can.run\", RUN_TARGETS)\n return { kind: \"grant\", capability: \"run\", target, selection }\n}\n\nfunction isAgentReference(input: unknown): input is AgentReference {\n return (\n typeof input === \"object\" &&\n input !== null &&\n !Array.isArray(input) &&\n !isBreadthSelector(input) &&\n \"kind\" in input &&\n input.kind === \"agent\"\n )\n}\n\nfunction isAgentUsageReference(input: unknown): input is AgentUsageReference {\n return (\n typeof input === \"object\" &&\n input !== null &&\n !Array.isArray(input) &&\n !isBreadthSelector(input) &&\n \"kind\" in input &&\n input.kind === \"aiUsage\"\n )\n}\n\nfunction observe(input: \"logs\" | AgentUsageReference): ObserveGrant {\n if (input !== \"logs\" && !isAgentUsageReference(input)) {\n throw new SecurityValidationError('[Sixb] can.observe accepts \"logs\" or agent.usage.')\n }\n const target = input === \"logs\" ? \"logs\" : \"aiUsage\"\n return {\n kind: \"grant\",\n capability: \"observe\",\n target,\n selection: { all: false, ids: [target] },\n }\n}\n\nfunction manage(input: GrantInput<ConnectorDefinition, \"connector\">): ManageGrant<\"connector\">\nfunction manage(input: AgentUsageReference): ManageGrant<\"aiUsage\">\nfunction manage(\n input: GrantInput<ConnectorDefinition, \"connector\"> | AgentUsageReference\n): ManageGrant {\n if (isAgentUsageReference(input)) {\n return {\n kind: \"grant\",\n capability: \"manage\",\n target: \"aiUsage\",\n selection: { all: false, ids: [\"aiUsage\"] },\n }\n }\n return {\n kind: \"grant\",\n capability: \"manage\",\n target: \"connector\",\n selection: resolveGrant(input, \"can.manage\", [\"connector\"]).selection,\n }\n}\n\nexport const can = {\n access,\n view,\n edit,\n append,\n apply,\n run,\n observe,\n manage,\n}\n",
|
|
15
|
+
"import { type ResolvedRole, resolveRoleGrants } from \"../authorization\"\nimport { APPLICATION_IDS } from \"./applications\"\nimport type { GroupDefinition, MembershipPolicyDefinition, RoleDefinition } from \"./types\"\nimport { validateSecurityDefinitionsAtStartup } from \"./validation\"\n\n/** Read-only access to validated security definitions and resolved role grants. */\nexport interface SecurityDefinitionCatalog {\n listGroups(): readonly GroupDefinition[]\n getGroupById(groupId: string): GroupDefinition | null\n listRoles(): readonly RoleDefinition[]\n getRoleById(roleId: string): RoleDefinition | null\n listResolvedRoles(): readonly ResolvedRole[]\n listMembershipPolicies(): readonly MembershipPolicyDefinition[]\n getMembershipPolicyById(policyId: string): MembershipPolicyDefinition | null\n}\n\nexport interface SecurityRegistryOptions {\n readonly groups?: readonly GroupDefinition[]\n readonly roles?: readonly RoleDefinition[]\n readonly membershipPolicies?: readonly MembershipPolicyDefinition[]\n readonly applicationIds?: ReadonlySet<string>\n readonly objectTypeIds?: ReadonlySet<string>\n readonly datasetIds?: ReadonlySet<string>\n readonly actionIds?: ReadonlySet<string>\n readonly workflowIds?: ReadonlySet<string>\n readonly syncIds?: ReadonlySet<string>\n readonly pipelineIds?: ReadonlySet<string>\n readonly agentAvailable?: boolean\n readonly connectorIds?: ReadonlySet<string>\n readonly getSubTypes?: (objectTypeId: string) => readonly string[]\n}\n\nexport class SecurityRegistry implements SecurityDefinitionCatalog {\n private readonly groupsById: ReadonlyMap<string, GroupDefinition>\n private readonly rolesById: ReadonlyMap<string, RoleDefinition>\n private readonly membershipPoliciesById: ReadonlyMap<string, MembershipPolicyDefinition>\n private readonly resolvedRoles: readonly ResolvedRole[]\n\n constructor(input: SecurityRegistryOptions) {\n const definitions = validateSecurityDefinitionsAtStartup({\n groups: input.groups ?? [],\n roles: input.roles ?? [],\n membershipPolicies: input.membershipPolicies ?? [],\n applicationIds: input.applicationIds ?? APPLICATION_IDS,\n objectTypeIds: input.objectTypeIds,\n datasetIds: input.datasetIds,\n actionIds: input.actionIds,\n workflowIds: input.workflowIds,\n syncIds: input.syncIds,\n pipelineIds: input.pipelineIds,\n agentAvailable: input.agentAvailable,\n connectorIds: input.connectorIds,\n observableIds: new Set([\"logs\", \"aiUsage\"]),\n manageableIds: new Set([\"aiUsage\"]),\n })\n\n const universe = {\n applicationIds: input.applicationIds ?? APPLICATION_IDS,\n objectTypeIds: input.objectTypeIds ?? new Set<string>(),\n datasetIds: input.datasetIds ?? new Set<string>(),\n actionIds: input.actionIds ?? new Set<string>(),\n workflowIds: input.workflowIds ?? new Set<string>(),\n syncIds: input.syncIds ?? new Set<string>(),\n pipelineIds: input.pipelineIds ?? new Set<string>(),\n connectorIds: input.connectorIds ?? new Set<string>(),\n observableIds: new Set([\"logs\", \"aiUsage\"]),\n manageableIds: new Set([\"aiUsage\"]),\n getSubTypes: input.getSubTypes ?? (() => []),\n }\n\n this.groupsById = definitions.groupsById\n this.rolesById = definitions.rolesById\n this.membershipPoliciesById = definitions.membershipPoliciesById\n this.resolvedRoles = definitions.roles.map((role) => ({\n id: role.id,\n grantedToGroupIds: role.grantedToGroupIds,\n grants: resolveRoleGrants(role, universe),\n }))\n }\n\n listGroups(): readonly GroupDefinition[] {\n return [...this.groupsById.values()]\n }\n\n getGroupById(groupId: string): GroupDefinition | null {\n return this.groupsById.get(groupId) ?? null\n }\n\n listRoles(): readonly RoleDefinition[] {\n return [...this.rolesById.values()]\n }\n\n getRoleById(roleId: string): RoleDefinition | null {\n return this.rolesById.get(roleId) ?? null\n }\n\n listResolvedRoles(): readonly ResolvedRole[] {\n return this.resolvedRoles\n }\n\n listMembershipPolicies(): readonly MembershipPolicyDefinition[] {\n return [...this.membershipPoliciesById.values()]\n }\n\n getMembershipPolicyById(policyId: string): MembershipPolicyDefinition | null {\n return this.membershipPoliciesById.get(policyId) ?? null\n }\n}\n",
|
|
16
|
+
"export type AuthStorageErrorCode =\n | \"device_authorization_denied\"\n | \"device_authorization_limit_exceeded\"\n | \"duplicate_device_authorization\"\n | \"duplicate_access_token\"\n | \"duplicate_identity\"\n | \"duplicate_invitation\"\n | \"duplicate_magic_link\"\n | \"duplicate_oidc_attempt\"\n | \"duplicate_service_account\"\n | \"duplicate_session\"\n | \"duplicate_user\"\n | \"email_link_not_allowed\"\n | \"expired_magic_link\"\n | \"expired_oidc_attempt\"\n | \"invalid_input\"\n | \"invalid_magic_link\"\n | \"invalid_oidc_attempt\"\n | \"invalid_device_authorization\"\n | \"missing_identity\"\n | \"missing_invitation\"\n | \"missing_magic_link\"\n | \"missing_oidc_attempt\"\n | \"missing_device_authorization\"\n | \"pending_device_authorization\"\n | \"missing_access_token\"\n | \"missing_service_account\"\n | \"missing_session\"\n | \"missing_user\"\n | \"suspended_service_account\"\n | \"suspended_user\"\n | \"user_creation_not_allowed\"\n\n/**\n * Error for auth storage invariants and invalid auth state transitions.\n */\nexport class AuthStorageError extends Error {\n readonly name = \"AuthStorageError\"\n\n constructor(\n readonly code: AuthStorageErrorCode,\n message: string\n ) {\n super(message)\n }\n}\n",
|
|
17
|
+
"import { type AuthSessionAudience, resolveAuthSessionAudience } from \"../../../auth/audience\"\nimport { AuthStorageError } from \"../errors\"\nimport type {\n AccessTokenRecord,\n CompleteAuthSessionInput,\n CreateAuthAccessTokenInput,\n CreateAuthServiceAccountInput,\n CreateAuthSessionInput,\n DeviceAuthorizationRecord,\n GroupMembershipRecord,\n InvitationRecord,\n MagicLinkRecord,\n OidcAuthorizationAttemptRecord,\n ServiceAccountGroupMembershipRecord,\n ServiceAccountRecord,\n SessionRecord,\n UpsertAuthGroupMembershipInput,\n UpsertAuthServiceAccountGroupMembershipInput,\n UserIdentityRecord,\n UserRecord,\n} from \"../types\"\n\nexport interface AuthStorageState {\n readonly users: Map<string, UserRecord>\n readonly identities: Map<string, UserIdentityRecord>\n readonly serviceAccounts: Map<string, ServiceAccountRecord>\n readonly serviceAccountGroupMemberships: Map<string, ServiceAccountGroupMembershipRecord>\n readonly sessions: Map<string, SessionRecord>\n readonly accessTokens: Map<string, AccessTokenRecord>\n readonly invitations: Map<string, InvitationRecord>\n readonly groupMemberships: Map<string, GroupMembershipRecord>\n readonly magicLinks: Map<string, MagicLinkRecord>\n readonly oidcAuthorizationAttempts: Map<string, OidcAuthorizationAttemptRecord>\n readonly deviceAuthorizations: Map<string, DeviceAuthorizationRecord>\n}\n\nexport function createAuthStorageState(): AuthStorageState {\n return {\n users: new Map(),\n identities: new Map(),\n serviceAccounts: new Map(),\n serviceAccountGroupMemberships: new Map(),\n sessions: new Map(),\n accessTokens: new Map(),\n invitations: new Map(),\n groupMemberships: new Map(),\n magicLinks: new Map(),\n oidcAuthorizationAttempts: new Map(),\n deviceAuthorizations: new Map(),\n }\n}\n\nfunction scopedKey(...parts: readonly string[]): string {\n return JSON.stringify(parts)\n}\n\nexport function userKey(projectId: string, id: string): string {\n return scopedKey(projectId, id)\n}\n\nexport function identityKey(projectId: string, strategyId: string, subject: string): string {\n return scopedKey(projectId, strategyId, subject)\n}\n\nexport function serviceAccountKey(projectId: string, id: string): string {\n return scopedKey(projectId, id)\n}\n\nexport function serviceAccountGroupMembershipKey(\n projectId: string,\n serviceAccountId: string,\n groupId: string\n): string {\n return scopedKey(projectId, serviceAccountId, groupId)\n}\n\nexport function sessionKey(projectId: string, id: string): string {\n return scopedKey(projectId, id)\n}\n\nexport function deviceAuthorizationKey(projectId: string, id: string): string {\n return scopedKey(projectId, id)\n}\n\nexport function accessTokenKey(projectId: string, id: string): string {\n return scopedKey(projectId, id)\n}\n\nexport function invitationKey(projectId: string, id: string): string {\n return scopedKey(projectId, id)\n}\n\nexport function groupMembershipKey(projectId: string, userId: string, groupId: string): string {\n return scopedKey(projectId, userId, groupId)\n}\n\nexport function magicLinkKey(projectId: string, id: string): string {\n return scopedKey(projectId, id)\n}\n\nexport function oidcAttemptKey(projectId: string, id: string): string {\n return scopedKey(projectId, id)\n}\n\nexport function cloneRecord<T>(record: T): T {\n return structuredClone(record)\n}\n\nexport function cloneOptionalRecord<T>(record: T | null): T | null {\n return record ? cloneRecord(record) : null\n}\n\nexport function cloneDate(value: Date): Date {\n return new Date(value)\n}\n\nexport function dateOrNow(value: Date | undefined): Date {\n return value ? cloneDate(value) : new Date()\n}\n\nexport function assertNonEmpty(value: string, label: string): string {\n const normalized = value.trim()\n if (!normalized) {\n throw new AuthStorageError(\"invalid_input\", `[Sixb] ${label} must be a non-empty string.`)\n }\n return normalized\n}\n\nexport function normalizeEmail(email: string): string {\n return assertNonEmpty(email, \"Email\").toLowerCase()\n}\n\nexport function normalizeGroupIds(groupIds: readonly string[] | undefined): readonly string[] {\n return [...new Set((groupIds ?? []).map((groupId) => assertNonEmpty(groupId, \"Group id\")))]\n}\n\nexport function normalizeOptionalGroupIds(\n groupIds: readonly string[] | undefined\n): readonly string[] | undefined {\n return groupIds === undefined ? undefined : normalizeGroupIds(groupIds)\n}\n\nexport function normalizeClaims(\n claims: Readonly<Record<string, unknown>> | undefined\n): Readonly<Record<string, unknown>> | undefined {\n return claims ? cloneRecord(claims) : undefined\n}\n\nexport function compareByCreatedAt<T extends { readonly id: string; readonly createdAt: Date }>(\n a: T,\n b: T,\n order: \"asc\" | \"desc\"\n): number {\n const delta = a.createdAt.getTime() - b.createdAt.getTime()\n if (delta !== 0) {\n return order === \"asc\" ? delta : -delta\n }\n\n return order === \"asc\" ? a.id.localeCompare(b.id) : b.id.localeCompare(a.id)\n}\n\nexport function isActiveSession(session: SessionRecord, now: Date): boolean {\n return (\n !session.revokedAt &&\n session.expiresAt > now &&\n (!session.absoluteExpiresAt || session.absoluteExpiresAt > now)\n )\n}\n\nexport function isActiveAccessToken(token: AccessTokenRecord, now: Date): boolean {\n return !token.revokedAt && token.expiresAt > now\n}\n\nexport function isActiveInvitation(invitation: InvitationRecord, now: Date): boolean {\n return invitation.status === \"pending\" && invitation.expiresAt > now\n}\n\nexport function isActiveMagicLink(link: MagicLinkRecord, now: Date): boolean {\n return !link.consumedAt && !link.revokedAt && link.expiresAt > now\n}\n\nexport function getUserByEmail(\n state: AuthStorageState,\n projectId: string,\n email: string\n): UserRecord | null {\n const normalizedEmail = normalizeEmail(email)\n for (const user of state.users.values()) {\n if (user.projectId === projectId && user.email === normalizedEmail) {\n return user\n }\n }\n return null\n}\n\nexport function getActiveInvitationByEmail(\n state: AuthStorageState,\n projectId: string,\n email: string,\n now: Date\n): InvitationRecord | null {\n const normalizedEmail = normalizeEmail(email)\n const invitations = [...state.invitations.values()]\n .filter((invitation) => invitation.projectId === projectId)\n .filter((invitation) => invitation.email === normalizedEmail)\n .filter((invitation) => isActiveInvitation(invitation, now))\n .sort((a, b) => compareByCreatedAt(a, b, \"desc\"))\n\n return invitations[0] ?? null\n}\n\nexport function revokeActiveSessionsForUser(\n state: AuthStorageState,\n projectId: string,\n userId: string,\n revokedAt: Date,\n audience?: AuthSessionAudience\n): readonly SessionRecord[] {\n const revoked: SessionRecord[] = []\n\n for (const [key, session] of state.sessions) {\n if (session.projectId !== projectId || session.userId !== userId) {\n continue\n }\n\n if (audience !== undefined && session.audience !== audience) {\n continue\n }\n\n if (!isActiveSession(session, revokedAt)) {\n continue\n }\n\n const next: SessionRecord = {\n ...session,\n revokedAt: cloneDate(revokedAt),\n }\n state.sessions.set(key, cloneRecord(next))\n revoked.push(next)\n }\n\n return revoked\n}\n\nexport function revokeActiveMagicLinksForEmail(\n state: AuthStorageState,\n projectId: string,\n email: string,\n revokedAt: Date\n): readonly MagicLinkRecord[] {\n const normalizedEmail = normalizeEmail(email)\n const revoked: MagicLinkRecord[] = []\n\n for (const [key, link] of state.magicLinks) {\n if (link.projectId !== projectId || link.email !== normalizedEmail) {\n continue\n }\n\n if (!isActiveMagicLink(link, revokedAt)) {\n continue\n }\n\n const next: MagicLinkRecord = {\n ...link,\n revokedAt: cloneDate(revokedAt),\n }\n state.magicLinks.set(key, cloneRecord(next))\n revoked.push(next)\n }\n\n return revoked\n}\n\nexport function assertSessionIdAvailable(\n state: AuthStorageState,\n projectId: string,\n sessionId: string\n): void {\n if (state.sessions.has(sessionKey(projectId, sessionId))) {\n throw new AuthStorageError(\n \"duplicate_session\",\n `[Sixb] Session '${sessionId}' already exists for project '${projectId}'.`\n )\n }\n}\n\nexport function validateCompleteSessionInput(\n state: AuthStorageState,\n projectId: string,\n session: CompleteAuthSessionInput\n): void {\n const sessionId = assertNonEmpty(session.id, \"Session id\")\n assertNonEmpty(session.audience, \"Session audience\")\n assertNonEmpty(session.tokenHash, \"Session token hash\")\n assertSessionIdAvailable(state, projectId, sessionId)\n}\n\nexport function createSessionRecord(\n state: AuthStorageState,\n input: CreateAuthSessionInput\n): SessionRecord {\n const id = assertNonEmpty(input.id, \"Session id\")\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const userId = assertNonEmpty(input.userId, \"User id\")\n const strategyId = assertNonEmpty(input.strategyId, \"Strategy id\")\n const audience = resolveAuthSessionAudience(input.audience)\n const tokenHash = assertNonEmpty(input.tokenHash, \"Session token hash\")\n\n assertSessionIdAvailable(state, projectId, id)\n\n const session: SessionRecord = {\n id,\n projectId,\n userId,\n strategyId,\n audience,\n tokenHash,\n createdAt: cloneDate(input.createdAt),\n expiresAt: cloneDate(input.expiresAt),\n absoluteExpiresAt: input.absoluteExpiresAt ? cloneDate(input.absoluteExpiresAt) : undefined,\n userAgent: input.userAgent,\n ipAddress: input.ipAddress,\n }\n\n state.sessions.set(sessionKey(projectId, id), cloneRecord(session))\n return session\n}\n\nexport function createServiceAccountRecord(\n state: AuthStorageState,\n input: CreateAuthServiceAccountInput\n): ServiceAccountRecord {\n const id = assertNonEmpty(input.id, \"Service account id\")\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const name = assertNonEmpty(input.name, \"Service account name\")\n const key = serviceAccountKey(projectId, id)\n\n if (state.serviceAccounts.has(key)) {\n throw new AuthStorageError(\n \"duplicate_service_account\",\n `[Sixb] Service account '${id}' already exists for project '${projectId}'.`\n )\n }\n\n const createdAt = dateOrNow(input.createdAt)\n const serviceAccount: ServiceAccountRecord = {\n id,\n projectId,\n name,\n description: input.description,\n status: input.status ?? \"active\",\n createdByPrincipal: input.createdByPrincipal,\n createdBySessionId: input.createdBySessionId,\n createdAt,\n updatedAt: input.updatedAt ? cloneDate(input.updatedAt) : cloneDate(createdAt),\n }\n\n state.serviceAccounts.set(key, cloneRecord(serviceAccount))\n return serviceAccount\n}\n\nexport function upsertServiceAccountGroupMembershipRecord(\n state: AuthStorageState,\n input: UpsertAuthServiceAccountGroupMembershipInput\n): ServiceAccountGroupMembershipRecord {\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const serviceAccountId = assertNonEmpty(input.serviceAccountId, \"Service account id\")\n const groupId = assertNonEmpty(input.groupId, \"Group id\")\n if (!state.serviceAccounts.has(serviceAccountKey(projectId, serviceAccountId))) {\n throw new AuthStorageError(\n \"missing_service_account\",\n `[Sixb] Service account '${serviceAccountId}' not found for project '${projectId}'.`\n )\n }\n\n const key = serviceAccountGroupMembershipKey(projectId, serviceAccountId, groupId)\n const existing = state.serviceAccountGroupMemberships.get(key)\n if (existing) {\n return existing\n }\n\n const membership: ServiceAccountGroupMembershipRecord = {\n projectId,\n serviceAccountId,\n groupId,\n source: input.source,\n createdAt: dateOrNow(input.createdAt),\n }\n\n state.serviceAccountGroupMemberships.set(key, cloneRecord(membership))\n return membership\n}\n\nexport function createAccessTokenRecord(\n state: AuthStorageState,\n input: CreateAuthAccessTokenInput\n): AccessTokenRecord {\n const id = assertNonEmpty(input.id, \"Access token id\")\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const name = assertNonEmpty(input.name, \"Access token name\")\n const subjectId = assertNonEmpty(input.subjectId, \"Access token subject id\")\n const tokenHash = assertNonEmpty(input.tokenHash, \"Access token hash\")\n\n assertAccessTokenSubject(input.kind, input.subjectType)\n assertAccessTokenSubjectExists(state, projectId, input.subjectType, subjectId)\n\n const key = accessTokenKey(projectId, id)\n if (state.accessTokens.has(key)) {\n throw new AuthStorageError(\n \"duplicate_access_token\",\n `[Sixb] Access token '${id}' already exists for project '${projectId}'.`\n )\n }\n\n const token: AccessTokenRecord = {\n id,\n projectId,\n name,\n kind: input.kind,\n subjectType: input.subjectType,\n subjectId,\n tokenHash,\n groupIds: normalizeOptionalGroupIds(input.groupIds),\n createdByPrincipal: input.createdByPrincipal,\n createdBySessionId: input.createdBySessionId,\n createdAt: cloneDate(input.createdAt),\n expiresAt: cloneDate(input.expiresAt),\n }\n\n state.accessTokens.set(key, cloneRecord(token))\n return token\n}\n\nexport function upsertGroupMembershipRecord(\n state: AuthStorageState,\n input: UpsertAuthGroupMembershipInput\n): GroupMembershipRecord {\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const userId = assertNonEmpty(input.userId, \"User id\")\n const groupId = assertNonEmpty(input.groupId, \"Group id\")\n if (!state.users.has(userKey(projectId, userId))) {\n throw new AuthStorageError(\n \"missing_user\",\n `[Sixb] User '${userId}' not found for project '${projectId}'.`\n )\n }\n\n const key = groupMembershipKey(projectId, userId, groupId)\n const existing = state.groupMemberships.get(key)\n\n if (existing) {\n return existing\n }\n\n const membership: GroupMembershipRecord = {\n projectId,\n userId,\n groupId,\n source: input.source,\n createdAt: dateOrNow(input.createdAt),\n }\n\n state.groupMemberships.set(key, cloneRecord(membership))\n return membership\n}\n\nexport function removeGroupMembershipRecord(\n state: AuthStorageState,\n params: { readonly projectId: string; readonly userId: string; readonly groupId: string }\n): GroupMembershipRecord | null {\n const projectId = assertNonEmpty(params.projectId, \"Project id\")\n const userId = assertNonEmpty(params.userId, \"User id\")\n const groupId = assertNonEmpty(params.groupId, \"Group id\")\n\n const key = groupMembershipKey(projectId, userId, groupId)\n const existing = state.groupMemberships.get(key)\n if (!existing) {\n return null\n }\n\n state.groupMemberships.delete(key)\n return existing\n}\n\nfunction assertAccessTokenSubject(\n kind: CreateAuthAccessTokenInput[\"kind\"],\n subjectType: CreateAuthAccessTokenInput[\"subjectType\"]\n): void {\n if (\n (kind === \"personal\" && subjectType === \"user\") ||\n (kind === \"serviceAccount\" && subjectType === \"serviceAccount\")\n ) {\n return\n }\n\n throw new AuthStorageError(\n \"invalid_input\",\n `[Sixb] Access token kind '${kind}' cannot target subject type '${subjectType}'.`\n )\n}\n\nfunction assertAccessTokenSubjectExists(\n state: AuthStorageState,\n projectId: string,\n subjectType: CreateAuthAccessTokenInput[\"subjectType\"],\n subjectId: string\n): void {\n if (subjectType === \"user\") {\n if (state.users.has(userKey(projectId, subjectId))) return\n throw new AuthStorageError(\n \"missing_user\",\n `[Sixb] User '${subjectId}' not found for project '${projectId}'.`\n )\n }\n\n if (state.serviceAccounts.has(serviceAccountKey(projectId, subjectId))) return\n throw new AuthStorageError(\n \"missing_service_account\",\n `[Sixb] Service account '${subjectId}' not found for project '${projectId}'.`\n )\n}\n\nexport function consumeMagicLinkRecord(\n state: AuthStorageState,\n params: {\n readonly projectId: string\n readonly id: string\n readonly tokenHash: string\n readonly consumedAt: Date\n }\n): MagicLinkRecord {\n const projectId = assertNonEmpty(params.projectId, \"Project id\")\n const id = assertNonEmpty(params.id, \"Magic link id\")\n const tokenHash = assertNonEmpty(params.tokenHash, \"Magic link token hash\")\n const key = magicLinkKey(projectId, id)\n const existing = state.magicLinks.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_magic_link\",\n `[Sixb] Magic link '${id}' not found for project '${projectId}'.`\n )\n }\n\n if (existing.tokenHash !== tokenHash || existing.consumedAt || existing.revokedAt) {\n throw new AuthStorageError(\n \"invalid_magic_link\",\n `[Sixb] Magic link '${id}' is not valid for project '${projectId}'.`\n )\n }\n\n if (existing.expiresAt <= params.consumedAt) {\n throw new AuthStorageError(\n \"expired_magic_link\",\n `[Sixb] Magic link '${id}' is expired for project '${projectId}'.`\n )\n }\n\n const consumed: MagicLinkRecord = {\n ...existing,\n consumedAt: cloneDate(params.consumedAt),\n }\n state.magicLinks.set(key, cloneRecord(consumed))\n return consumed\n}\n\nexport function consumeOidcAttemptRecord(\n state: AuthStorageState,\n params: {\n readonly projectId: string\n readonly id: string\n readonly stateHash: string\n readonly consumedAt: Date\n }\n): OidcAuthorizationAttemptRecord {\n const projectId = assertNonEmpty(params.projectId, \"Project id\")\n const id = assertNonEmpty(params.id, \"OIDC authorization attempt id\")\n const stateHash = assertNonEmpty(params.stateHash, \"OIDC state hash\")\n const key = oidcAttemptKey(projectId, id)\n const existing = state.oidcAuthorizationAttempts.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_oidc_attempt\",\n `[Sixb] OIDC authorization attempt '${id}' not found for project '${projectId}'.`\n )\n }\n\n if (existing.stateHash !== stateHash || existing.consumedAt) {\n throw new AuthStorageError(\n \"invalid_oidc_attempt\",\n `[Sixb] OIDC authorization attempt '${id}' is not valid for project '${projectId}'.`\n )\n }\n\n if (existing.expiresAt <= params.consumedAt) {\n throw new AuthStorageError(\n \"expired_oidc_attempt\",\n `[Sixb] OIDC authorization attempt '${id}' is expired for project '${projectId}'.`\n )\n }\n\n const consumed: OidcAuthorizationAttemptRecord = {\n ...existing,\n consumedAt: cloneDate(params.consumedAt),\n }\n state.oidcAuthorizationAttempts.set(key, cloneRecord(consumed))\n return consumed\n}\n",
|
|
18
|
+
"import { AuthStorageError } from \"../errors\"\nimport type {\n AccessTokenRecord,\n AuthAccessTokenStore,\n CreateAuthAccessTokenInput,\n ListAuthAccessTokensInput,\n ListAuthAccessTokensResult,\n} from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n accessTokenKey,\n cloneDate,\n cloneOptionalRecord,\n cloneRecord,\n compareByCreatedAt,\n createAccessTokenRecord,\n isActiveAccessToken,\n} from \"./shared\"\n\nexport class InMemoryAuthAccessTokenStore implements AuthAccessTokenStore {\n constructor(private readonly state: AuthStorageState) {}\n\n async create(input: CreateAuthAccessTokenInput): Promise<AccessTokenRecord> {\n return cloneRecord(createAccessTokenRecord(this.state, input))\n }\n\n async getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<AccessTokenRecord | null> {\n const record = this.state.accessTokens.get(accessTokenKey(params.projectId, params.id)) ?? null\n return cloneOptionalRecord(record)\n }\n\n async list(input: ListAuthAccessTokensInput): Promise<ListAuthAccessTokensResult> {\n const order = input.order ?? \"asc\"\n const offset = input.offset ?? 0\n const rows = [...this.state.accessTokens.values()]\n .filter((token) => token.projectId === input.projectId)\n .filter((token) => input.kind === undefined || token.kind === input.kind)\n .filter((token) => input.subjectType === undefined || token.subjectType === input.subjectType)\n .filter((token) => input.subjectId === undefined || token.subjectId === input.subjectId)\n .filter((token) => input.includeRevoked || !token.revokedAt)\n .sort((a, b) => compareByCreatedAt(a, b, order))\n const page = rows.slice(offset, input.limit === undefined ? undefined : offset + input.limit)\n\n return {\n accessTokens: page.map(cloneRecord),\n hasMore: input.limit === undefined ? false : offset + input.limit < rows.length,\n total: rows.length,\n }\n }\n\n async findValidByTokenHash(params: {\n readonly projectId: string\n readonly id: string\n readonly kind: AccessTokenRecord[\"kind\"]\n readonly tokenHash: string\n readonly now: Date\n }): Promise<AccessTokenRecord | null> {\n const token = this.state.accessTokens.get(accessTokenKey(params.projectId, params.id))\n if (\n !token ||\n token.kind !== params.kind ||\n token.tokenHash !== params.tokenHash ||\n !isActiveAccessToken(token, params.now)\n ) {\n return null\n }\n\n return cloneRecord(token)\n }\n\n async revoke(params: {\n readonly projectId: string\n readonly id: string\n readonly revokedAt: Date\n }): Promise<AccessTokenRecord> {\n const key = accessTokenKey(params.projectId, params.id)\n const existing = this.state.accessTokens.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_access_token\",\n `[Sixb] Access token '${params.id}' not found for project '${params.projectId}'.`\n )\n }\n\n const next: AccessTokenRecord = {\n ...existing,\n revokedAt: cloneDate(params.revokedAt),\n }\n this.state.accessTokens.set(key, cloneRecord(next))\n return cloneRecord(next)\n }\n\n async touch(params: {\n readonly projectId: string\n readonly id: string\n readonly lastUsedAt: Date\n readonly userAgent?: string\n readonly ipAddress?: string\n }): Promise<AccessTokenRecord> {\n const key = accessTokenKey(params.projectId, params.id)\n const existing = this.state.accessTokens.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_access_token\",\n `[Sixb] Access token '${params.id}' not found for project '${params.projectId}'.`\n )\n }\n\n const next: AccessTokenRecord = {\n ...existing,\n lastUsedAt: cloneDate(params.lastUsedAt),\n lastUsedUserAgent: params.userAgent ?? existing.lastUsedUserAgent,\n lastUsedIpAddress: params.ipAddress ?? existing.lastUsedIpAddress,\n }\n this.state.accessTokens.set(key, cloneRecord(next))\n return cloneRecord(next)\n }\n}\n",
|
|
19
|
+
"import type { AccessTokenKind, AuthSessionAudience, Principal } from \"../../auth\"\n\nexport type UserStatus = \"active\" | \"suspended\"\nexport type ServiceAccountStatus = \"active\" | \"suspended\"\nexport type InvitationStatus = \"pending\" | \"accepted\" | \"revoked\"\nexport type GroupMembershipSource = \"invitation\" | \"manual\" | \"agent\"\nexport type AccessTokenSubjectType = \"user\" | \"serviceAccount\"\nexport type DeviceAuthorizationStatus = \"pending\" | \"approved\" | \"denied\" | \"consumed\"\nexport const MAX_PENDING_DEVICE_AUTHORIZATIONS = 100\n\nexport interface UserRecord {\n readonly id: string\n readonly projectId: string\n readonly email: string\n readonly displayName?: string\n readonly avatarUrl?: string\n readonly status: UserStatus\n readonly createdAt: Date\n readonly updatedAt: Date\n}\n\nexport interface UserIdentityRecord {\n readonly projectId: string\n readonly strategyId: string\n readonly subject: string\n readonly userId: string\n readonly claims?: Readonly<Record<string, unknown>>\n readonly createdAt: Date\n readonly updatedAt: Date\n}\n\nexport interface ServiceAccountRecord {\n readonly id: string\n readonly projectId: string\n readonly name: string\n readonly description?: string\n readonly status: ServiceAccountStatus\n readonly createdByPrincipal?: Principal\n readonly createdBySessionId?: string\n readonly createdAt: Date\n readonly updatedAt: Date\n}\n\nexport interface ServiceAccountGroupMembershipRecord {\n readonly projectId: string\n readonly serviceAccountId: string\n readonly groupId: string\n readonly source: GroupMembershipSource\n readonly createdAt: Date\n}\n\nexport interface SessionRecord {\n readonly id: string\n readonly projectId: string\n readonly userId: string\n readonly strategyId: string\n readonly audience: AuthSessionAudience\n readonly tokenHash: string\n readonly createdAt: Date\n readonly expiresAt: Date\n readonly absoluteExpiresAt?: Date\n readonly revokedAt?: Date\n readonly lastSeenAt?: Date\n // Best-effort client metadata captured at sign-in, for the active-sessions\n // view. Display only — never used for authorization.\n readonly userAgent?: string\n readonly ipAddress?: string\n}\n\nexport interface AccessTokenRecord {\n readonly id: string\n readonly projectId: string\n readonly name: string\n readonly kind: AccessTokenKind\n readonly subjectType: AccessTokenSubjectType\n readonly subjectId: string\n readonly tokenHash: string\n /**\n * Optional group constraint. Undefined means \"inherit every current group\";\n * an empty array means the token authenticates but has no group-derived grants.\n */\n readonly groupIds?: readonly string[]\n readonly createdByPrincipal?: Principal\n readonly createdBySessionId?: string\n readonly createdAt: Date\n readonly expiresAt: Date\n readonly revokedAt?: Date\n readonly lastUsedAt?: Date\n // Best-effort client metadata for audit/debugging. Display only.\n readonly lastUsedUserAgent?: string\n readonly lastUsedIpAddress?: string\n}\n\nexport interface InvitationRecord {\n readonly id: string\n readonly projectId: string\n readonly email: string\n readonly groupIds: readonly string[]\n readonly status: InvitationStatus\n readonly createdByPrincipal?: Principal\n readonly createdBySessionId?: string\n readonly createdAt: Date\n readonly updatedAt: Date\n readonly expiresAt: Date\n readonly acceptedAt?: Date\n readonly revokedAt?: Date\n}\n\nexport interface GroupMembershipRecord {\n readonly projectId: string\n readonly userId: string\n readonly groupId: string\n readonly source: GroupMembershipSource\n readonly createdAt: Date\n}\n\nexport interface MagicLinkRecord {\n readonly id: string\n readonly projectId: string\n readonly strategyId: string\n readonly audience: AuthSessionAudience\n readonly email: string\n readonly tokenHash: string\n readonly returnTo?: string\n readonly createdAt: Date\n readonly expiresAt: Date\n readonly consumedAt?: Date\n readonly revokedAt?: Date\n}\n\nexport interface OidcAuthorizationAttemptRecord {\n readonly id: string\n readonly projectId: string\n readonly strategyId: string\n readonly audience: AuthSessionAudience\n readonly stateHash: string\n readonly nonceHash: string\n readonly codeVerifier: string\n readonly returnTo?: string\n readonly createdAt: Date\n readonly expiresAt: Date\n readonly consumedAt?: Date\n}\n\nexport interface DeviceAuthorizationRecord {\n readonly id: string\n readonly projectId: string\n readonly deviceCodeHash: string\n readonly userCode: string\n readonly clientName: string\n readonly tokenName: string\n readonly tokenExpiresAt: Date\n readonly status: DeviceAuthorizationStatus\n readonly approvedUserId?: string\n readonly approvedSessionId?: string\n readonly createdAt: Date\n readonly expiresAt: Date\n readonly approvedAt?: Date\n readonly deniedAt?: Date\n readonly consumedAt?: Date\n}\n\nexport interface CreateAuthUserInput {\n readonly id: string\n readonly projectId: string\n readonly email: string\n readonly displayName?: string\n readonly avatarUrl?: string\n readonly status?: UserStatus\n readonly createdAt?: Date\n readonly updatedAt?: Date\n}\n\nexport interface UpdateAuthUserProfileInput {\n readonly projectId: string\n readonly id: string\n readonly displayName?: string\n readonly avatarUrl?: string\n readonly updatedAt?: Date\n}\n\nexport interface UpdateAuthUserStatusInput {\n readonly projectId: string\n readonly id: string\n readonly status: UserStatus\n readonly updatedAt?: Date\n}\n\nexport interface ListAuthUsersInput {\n readonly projectId: string\n readonly statuses?: readonly UserStatus[]\n readonly limit?: number\n readonly offset?: number\n readonly order?: \"asc\" | \"desc\"\n}\n\nexport interface ListAuthUsersResult {\n readonly users: readonly UserRecord[]\n readonly hasMore: boolean\n readonly total: number\n}\n\nexport interface UpsertAuthUserIdentityInput {\n readonly projectId: string\n readonly strategyId: string\n readonly subject: string\n readonly userId: string\n readonly claims?: Readonly<Record<string, unknown>>\n readonly createdAt?: Date\n readonly updatedAt?: Date\n}\n\nexport interface CreateAuthServiceAccountInput {\n readonly id: string\n readonly projectId: string\n readonly name: string\n readonly description?: string\n readonly status?: ServiceAccountStatus\n readonly createdByPrincipal?: Principal\n readonly createdBySessionId?: string\n readonly createdAt?: Date\n readonly updatedAt?: Date\n}\n\nexport interface UpdateAuthServiceAccountInput {\n readonly projectId: string\n readonly id: string\n readonly name?: string\n readonly description?: string\n readonly status?: ServiceAccountStatus\n readonly updatedAt?: Date\n}\n\nexport interface ListAuthServiceAccountsInput {\n readonly projectId: string\n readonly statuses?: readonly ServiceAccountStatus[]\n readonly limit?: number\n readonly offset?: number\n readonly order?: \"asc\" | \"desc\"\n}\n\nexport interface ListAuthServiceAccountsResult {\n readonly serviceAccounts: readonly ServiceAccountRecord[]\n readonly hasMore: boolean\n readonly total: number\n}\n\nexport interface UpsertAuthServiceAccountGroupMembershipInput {\n readonly projectId: string\n readonly serviceAccountId: string\n readonly groupId: string\n readonly source: GroupMembershipSource\n readonly createdAt?: Date\n}\n\nexport interface ReconcileAuthServiceAccountGroupMembershipsInput {\n readonly projectId: string\n readonly serviceAccountId: string\n readonly groupIds: readonly string[]\n readonly source: \"agent\"\n readonly updatedAt?: Date\n}\n\nexport interface CreateAuthSessionInput {\n readonly id: string\n readonly projectId: string\n readonly userId: string\n readonly strategyId: string\n readonly audience: AuthSessionAudience\n readonly tokenHash: string\n readonly createdAt: Date\n readonly expiresAt: Date\n readonly absoluteExpiresAt?: Date\n readonly userAgent?: string\n readonly ipAddress?: string\n}\n\nexport interface CreateAuthAccessTokenInput {\n readonly id: string\n readonly projectId: string\n readonly name: string\n readonly kind: AccessTokenKind\n readonly subjectType: AccessTokenSubjectType\n readonly subjectId: string\n readonly tokenHash: string\n readonly groupIds?: readonly string[]\n readonly createdByPrincipal?: Principal\n readonly createdBySessionId?: string\n readonly createdAt: Date\n readonly expiresAt: Date\n}\n\nexport interface ListAuthAccessTokensInput {\n readonly projectId: string\n readonly kind?: AccessTokenKind\n readonly subjectType?: AccessTokenSubjectType\n readonly subjectId?: string\n readonly includeRevoked?: boolean\n readonly limit?: number\n readonly offset?: number\n readonly order?: \"asc\" | \"desc\"\n}\n\nexport interface ListAuthAccessTokensResult {\n readonly accessTokens: readonly AccessTokenRecord[]\n readonly hasMore: boolean\n readonly total: number\n}\n\nexport interface CompleteAuthSessionInput {\n readonly id: string\n readonly audience: AuthSessionAudience\n readonly tokenHash: string\n readonly createdAt: Date\n readonly expiresAt: Date\n readonly absoluteExpiresAt?: Date\n readonly userAgent?: string\n readonly ipAddress?: string\n}\n\nexport interface CreateOrUpdateAuthInvitationInput {\n readonly id: string\n readonly projectId: string\n readonly email: string\n readonly groupIds?: readonly string[]\n readonly createdByPrincipal?: Principal\n readonly createdBySessionId?: string\n readonly createdAt?: Date\n readonly updatedAt?: Date\n readonly expiresAt: Date\n}\n\nexport interface ListAuthInvitationsInput {\n readonly projectId: string\n readonly email?: string\n readonly statuses?: readonly InvitationStatus[]\n readonly groupIds?: readonly string[]\n readonly limit?: number\n readonly offset?: number\n readonly order?: \"asc\" | \"desc\"\n}\n\nexport interface ListAuthInvitationsResult {\n readonly invitations: readonly InvitationRecord[]\n readonly hasMore: boolean\n readonly total: number\n}\n\nexport interface UpsertAuthGroupMembershipInput {\n readonly projectId: string\n readonly userId: string\n readonly groupId: string\n readonly source: GroupMembershipSource\n readonly createdAt?: Date\n}\n\nexport interface CreateAuthMagicLinkInput {\n readonly id: string\n readonly projectId: string\n readonly strategyId: string\n readonly audience: AuthSessionAudience\n readonly email: string\n readonly tokenHash: string\n readonly returnTo?: string\n readonly createdAt: Date\n readonly expiresAt: Date\n}\n\nexport interface CreateOidcAuthorizationAttemptInput {\n readonly id: string\n readonly projectId: string\n readonly strategyId: string\n readonly audience: AuthSessionAudience\n readonly stateHash: string\n readonly nonceHash: string\n readonly codeVerifier: string\n readonly returnTo?: string\n readonly createdAt: Date\n readonly expiresAt: Date\n}\n\nexport interface CreateDeviceAuthorizationInput {\n readonly id: string\n readonly projectId: string\n readonly deviceCodeHash: string\n readonly userCode: string\n readonly clientName: string\n readonly tokenName: string\n readonly tokenExpiresAt: Date\n readonly createdAt: Date\n readonly expiresAt: Date\n}\n\nexport interface CompleteDeviceAuthorizationInput {\n readonly projectId: string\n readonly id: string\n readonly deviceCodeHash: string\n readonly accessToken: CreateAuthAccessTokenInput\n readonly completedAt: Date\n}\n\nexport interface CompleteDeviceAuthorizationResult {\n readonly authorization: DeviceAuthorizationRecord\n readonly accessToken: AccessTokenRecord\n}\n\nexport interface CompleteMagicLinkSignInInput {\n readonly projectId: string\n readonly magicLinkId: string\n readonly tokenHash: string\n readonly completedAt: Date\n readonly newUserId: string\n readonly newUserDisplayName?: string\n readonly newUserAvatarUrl?: string\n readonly allowUserCreationWithoutInvitation?: boolean\n readonly requireNoActiveUsersForUserCreation?: boolean\n readonly manualGroupIds?: readonly string[]\n readonly session: CompleteAuthSessionInput\n}\n\nexport interface CompleteOidcSignInInput {\n readonly projectId: string\n readonly oidcAuthorizationAttemptId: string\n readonly stateHash: string\n readonly completedAt: Date\n readonly subject: string\n readonly email: string\n readonly emailVerified?: boolean\n readonly displayName?: string\n readonly avatarUrl?: string\n readonly claims?: Readonly<Record<string, unknown>>\n readonly autoLinkByVerifiedEmail?: boolean\n readonly allowUserCreationWithoutInvitation?: boolean\n readonly requireNoActiveUsersForUserCreation?: boolean\n readonly manualGroupIds?: readonly string[]\n readonly newUserId: string\n readonly session: CompleteAuthSessionInput\n}\n\nexport interface CompleteSignInResult {\n readonly user: UserRecord\n readonly session: SessionRecord\n readonly identity?: UserIdentityRecord\n readonly invitation?: InvitationRecord\n readonly groupMemberships: readonly GroupMembershipRecord[]\n}\n\nexport interface SuspendUserAndRevokeSessionsInput {\n readonly projectId: string\n readonly userId: string\n readonly suspendedAt: Date\n}\n\nexport interface AuthUserStore {\n create(input: CreateAuthUserInput): Promise<UserRecord>\n getById(params: { readonly projectId: string; readonly id: string }): Promise<UserRecord | null>\n getByEmail(params: {\n readonly projectId: string\n readonly email: string\n }): Promise<UserRecord | null>\n updateProfile(input: UpdateAuthUserProfileInput): Promise<UserRecord>\n updateStatus(input: UpdateAuthUserStatusInput): Promise<UserRecord>\n list(input: ListAuthUsersInput): Promise<ListAuthUsersResult>\n}\n\nexport interface AuthUserIdentityStore {\n upsert(input: UpsertAuthUserIdentityInput): Promise<UserIdentityRecord>\n getBySubject(params: {\n readonly projectId: string\n readonly strategyId: string\n readonly subject: string\n }): Promise<UserIdentityRecord | null>\n listForUser(params: {\n readonly projectId: string\n readonly userId: string\n }): Promise<readonly UserIdentityRecord[]>\n}\n\nexport interface AuthServiceAccountStore {\n create(input: CreateAuthServiceAccountInput): Promise<ServiceAccountRecord>\n getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<ServiceAccountRecord | null>\n /** Update only the provided fields; omitted fields must remain unchanged atomically. */\n update(input: UpdateAuthServiceAccountInput): Promise<ServiceAccountRecord>\n list(input: ListAuthServiceAccountsInput): Promise<ListAuthServiceAccountsResult>\n}\n\nexport interface AuthServiceAccountGroupMembershipStore {\n upsert(\n input: UpsertAuthServiceAccountGroupMembershipInput\n ): Promise<ServiceAccountGroupMembershipRecord>\n reconcileForServiceAccount(\n input: ReconcileAuthServiceAccountGroupMembershipsInput\n ): Promise<readonly ServiceAccountGroupMembershipRecord[]>\n listForServiceAccount(params: {\n readonly projectId: string\n readonly serviceAccountId: string\n }): Promise<readonly ServiceAccountGroupMembershipRecord[]>\n listForGroup(params: {\n readonly projectId: string\n readonly groupId: string\n }): Promise<readonly ServiceAccountGroupMembershipRecord[]>\n}\n\nexport interface AuthSessionStore {\n create(input: CreateAuthSessionInput): Promise<SessionRecord>\n getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<SessionRecord | null>\n getActiveByUserId(params: {\n readonly projectId: string\n readonly userId: string\n readonly audience: AuthSessionAudience\n readonly now: Date\n }): Promise<SessionRecord | null>\n // All active sessions for a user across every audience, most-recently-active\n // first. Backs the active-sessions view.\n listActiveByUserId(params: {\n readonly projectId: string\n readonly userId: string\n readonly now: Date\n }): Promise<readonly SessionRecord[]>\n findValidByTokenHash(params: {\n readonly projectId: string\n readonly id: string\n readonly audience: AuthSessionAudience\n readonly tokenHash: string\n readonly now: Date\n }): Promise<SessionRecord | null>\n renewIfValid(params: {\n readonly projectId: string\n readonly id: string\n readonly audience: AuthSessionAudience\n readonly tokenHash: string\n readonly now: Date\n readonly expiresAt: Date\n }): Promise<SessionRecord | null>\n revoke(params: {\n readonly projectId: string\n readonly id: string\n readonly revokedAt: Date\n }): Promise<SessionRecord>\n revokeActiveForUser(params: {\n readonly projectId: string\n readonly userId: string\n readonly audience?: AuthSessionAudience\n readonly revokedAt: Date\n }): Promise<readonly SessionRecord[]>\n touch(params: {\n readonly projectId: string\n readonly id: string\n readonly lastSeenAt: Date\n }): Promise<SessionRecord>\n}\n\nexport interface AuthAccessTokenStore {\n create(input: CreateAuthAccessTokenInput): Promise<AccessTokenRecord>\n getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<AccessTokenRecord | null>\n list(input: ListAuthAccessTokensInput): Promise<ListAuthAccessTokensResult>\n findValidByTokenHash(params: {\n readonly projectId: string\n readonly id: string\n readonly kind: AccessTokenKind\n readonly tokenHash: string\n readonly now: Date\n }): Promise<AccessTokenRecord | null>\n revoke(params: {\n readonly projectId: string\n readonly id: string\n readonly revokedAt: Date\n }): Promise<AccessTokenRecord>\n touch(params: {\n readonly projectId: string\n readonly id: string\n readonly lastUsedAt: Date\n readonly userAgent?: string\n readonly ipAddress?: string\n }): Promise<AccessTokenRecord>\n}\n\nexport interface AuthInvitationStore {\n createOrUpdateActive(input: CreateOrUpdateAuthInvitationInput): Promise<InvitationRecord>\n getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<InvitationRecord | null>\n getActiveByEmail(params: {\n readonly projectId: string\n readonly email: string\n readonly now: Date\n }): Promise<InvitationRecord | null>\n list(input: ListAuthInvitationsInput): Promise<ListAuthInvitationsResult>\n accept(params: {\n readonly projectId: string\n readonly id: string\n readonly acceptedAt: Date\n }): Promise<InvitationRecord>\n revoke(params: {\n readonly projectId: string\n readonly id: string\n readonly revokedAt: Date\n }): Promise<InvitationRecord>\n}\n\nexport interface AuthGroupMembershipStore {\n upsert(input: UpsertAuthGroupMembershipInput): Promise<GroupMembershipRecord>\n /**\n * Removes a single group membership. Returns the removed record, or `null` when\n * no matching membership exists (including for a missing user). Idempotent.\n */\n remove(params: {\n readonly projectId: string\n readonly userId: string\n readonly groupId: string\n }): Promise<GroupMembershipRecord | null>\n listForUser(params: {\n readonly projectId: string\n readonly userId: string\n }): Promise<readonly GroupMembershipRecord[]>\n listForGroup(params: {\n readonly projectId: string\n readonly groupId: string\n }): Promise<readonly GroupMembershipRecord[]>\n}\n\nexport interface AuthMagicLinkStore {\n create(input: CreateAuthMagicLinkInput): Promise<MagicLinkRecord>\n getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<MagicLinkRecord | null>\n getActiveByEmail(params: {\n readonly projectId: string\n readonly email: string\n readonly now: Date\n }): Promise<MagicLinkRecord | null>\n consume(params: {\n readonly projectId: string\n readonly id: string\n readonly tokenHash: string\n readonly consumedAt: Date\n }): Promise<MagicLinkRecord>\n revokeActiveForEmail(params: {\n readonly projectId: string\n readonly email: string\n readonly revokedAt: Date\n }): Promise<readonly MagicLinkRecord[]>\n}\n\nexport interface AuthOidcAuthorizationAttemptStore {\n create(input: CreateOidcAuthorizationAttemptInput): Promise<OidcAuthorizationAttemptRecord>\n getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<OidcAuthorizationAttemptRecord | null>\n consume(params: {\n readonly projectId: string\n readonly id: string\n readonly stateHash: string\n readonly consumedAt: Date\n }): Promise<OidcAuthorizationAttemptRecord>\n}\n\nexport interface AuthDeviceAuthorizationStore {\n create(input: CreateDeviceAuthorizationInput): Promise<DeviceAuthorizationRecord>\n getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<DeviceAuthorizationRecord | null>\n getByUserCode(params: {\n readonly projectId: string\n readonly userCode: string\n }): Promise<DeviceAuthorizationRecord | null>\n approve(params: {\n readonly projectId: string\n readonly id: string\n readonly userId: string\n readonly sessionId: string\n readonly approvedAt: Date\n }): Promise<DeviceAuthorizationRecord>\n deny(params: {\n readonly projectId: string\n readonly id: string\n readonly deniedAt: Date\n }): Promise<DeviceAuthorizationRecord>\n}\n\nexport interface AuthStorage {\n readonly users: AuthUserStore\n readonly identities: AuthUserIdentityStore\n readonly serviceAccounts: AuthServiceAccountStore\n readonly serviceAccountGroupMemberships: AuthServiceAccountGroupMembershipStore\n readonly sessions: AuthSessionStore\n readonly accessTokens: AuthAccessTokenStore\n readonly invitations: AuthInvitationStore\n readonly groupMemberships: AuthGroupMembershipStore\n readonly magicLinks: AuthMagicLinkStore\n readonly oidcAuthorizationAttempts: AuthOidcAuthorizationAttemptStore\n readonly deviceAuthorizations: AuthDeviceAuthorizationStore\n\n completeMagicLinkSignIn(input: CompleteMagicLinkSignInInput): Promise<CompleteSignInResult>\n completeOidcSignIn(input: CompleteOidcSignInInput): Promise<CompleteSignInResult>\n completeDeviceAuthorization(\n input: CompleteDeviceAuthorizationInput\n ): Promise<CompleteDeviceAuthorizationResult>\n suspendUserAndRevokeSessions(input: SuspendUserAndRevokeSessionsInput): Promise<UserRecord>\n}\n",
|
|
20
|
+
"import { AuthStorageError } from \"../errors\"\nimport type {\n AuthDeviceAuthorizationStore,\n CreateDeviceAuthorizationInput,\n DeviceAuthorizationRecord,\n} from \"../types\"\nimport { MAX_PENDING_DEVICE_AUTHORIZATIONS } from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n assertNonEmpty,\n cloneRecord,\n deviceAuthorizationKey,\n isActiveSession,\n sessionKey,\n userKey,\n} from \"./shared\"\n\nexport class InMemoryAuthDeviceAuthorizationStore implements AuthDeviceAuthorizationStore {\n constructor(private readonly state: AuthStorageState) {}\n\n async create(input: CreateDeviceAuthorizationInput): Promise<DeviceAuthorizationRecord> {\n const id = assertNonEmpty(input.id, \"Device authorization id\")\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n for (const [key, authorization] of this.state.deviceAuthorizations) {\n if (authorization.projectId === projectId && authorization.expiresAt <= input.createdAt) {\n this.state.deviceAuthorizations.delete(key)\n }\n }\n const pending = [...this.state.deviceAuthorizations.values()].filter(\n (authorization) => authorization.projectId === projectId && authorization.status === \"pending\"\n ).length\n if (pending >= MAX_PENDING_DEVICE_AUTHORIZATIONS) {\n throw new AuthStorageError(\n \"device_authorization_limit_exceeded\",\n `[Sixb] Project '${projectId}' has too many pending device authorizations.`\n )\n }\n const key = deviceAuthorizationKey(projectId, id)\n if (this.state.deviceAuthorizations.has(key)) {\n throw duplicateAuthorization(id, projectId)\n }\n const record: DeviceAuthorizationRecord = {\n id,\n projectId,\n deviceCodeHash: assertNonEmpty(input.deviceCodeHash, \"Device code hash\"),\n userCode: assertNonEmpty(input.userCode, \"User code\"),\n clientName: assertNonEmpty(input.clientName, \"Client name\"),\n tokenName: assertNonEmpty(input.tokenName, \"Token name\"),\n tokenExpiresAt: new Date(input.tokenExpiresAt),\n status: \"pending\",\n createdAt: new Date(input.createdAt),\n expiresAt: new Date(input.expiresAt),\n }\n this.state.deviceAuthorizations.set(key, cloneRecord(record))\n return cloneRecord(record)\n }\n\n async getById(params: { readonly projectId: string; readonly id: string }) {\n const record = this.state.deviceAuthorizations.get(\n deviceAuthorizationKey(params.projectId, params.id)\n )\n return record ? cloneRecord(record) : null\n }\n\n async getByUserCode(params: { readonly projectId: string; readonly userCode: string }) {\n for (const record of this.state.deviceAuthorizations.values()) {\n if (record.projectId === params.projectId && record.userCode === params.userCode) {\n return cloneRecord(record)\n }\n }\n return null\n }\n\n async approve(params: {\n readonly projectId: string\n readonly id: string\n readonly userId: string\n readonly sessionId: string\n readonly approvedAt: Date\n }): Promise<DeviceAuthorizationRecord> {\n const record = this.requirePending(params.projectId, params.id, params.approvedAt)\n const user = this.state.users.get(userKey(params.projectId, params.userId))\n const session = this.state.sessions.get(sessionKey(params.projectId, params.sessionId))\n if (\n !user ||\n user.status !== \"active\" ||\n !session ||\n session.userId !== user.id ||\n !isActiveSession(session, params.approvedAt)\n ) {\n throw new AuthStorageError(\n \"invalid_device_authorization\",\n \"[Sixb] Device authorization requires an active user session.\"\n )\n }\n const next: DeviceAuthorizationRecord = {\n ...record,\n status: \"approved\",\n approvedUserId: assertNonEmpty(params.userId, \"Approved user id\"),\n approvedSessionId: assertNonEmpty(params.sessionId, \"Approved session id\"),\n approvedAt: new Date(params.approvedAt),\n }\n this.state.deviceAuthorizations.set(deviceAuthorizationKey(params.projectId, params.id), next)\n return cloneRecord(next)\n }\n\n async deny(params: {\n readonly projectId: string\n readonly id: string\n readonly deniedAt: Date\n }): Promise<DeviceAuthorizationRecord> {\n const record = this.requirePending(params.projectId, params.id, params.deniedAt)\n const next: DeviceAuthorizationRecord = {\n ...record,\n status: \"denied\",\n deniedAt: new Date(params.deniedAt),\n }\n this.state.deviceAuthorizations.set(deviceAuthorizationKey(params.projectId, params.id), next)\n return cloneRecord(next)\n }\n\n private requirePending(projectId: string, id: string, now: Date): DeviceAuthorizationRecord {\n const record = this.state.deviceAuthorizations.get(deviceAuthorizationKey(projectId, id))\n if (!record) {\n throw new AuthStorageError(\n \"missing_device_authorization\",\n `[Sixb] Device authorization '${id}' not found for project '${projectId}'.`\n )\n }\n if (record.status !== \"pending\" || record.expiresAt <= now) {\n throw new AuthStorageError(\n \"invalid_device_authorization\",\n `[Sixb] Device authorization '${id}' is no longer pending for project '${projectId}'.`\n )\n }\n return record\n }\n}\n\nfunction duplicateAuthorization(id: string, projectId: string): AuthStorageError {\n return new AuthStorageError(\n \"duplicate_device_authorization\",\n `[Sixb] Device authorization '${id}' already exists for project '${projectId}'.`\n )\n}\n",
|
|
21
|
+
"import type {\n AuthGroupMembershipStore,\n GroupMembershipRecord,\n UpsertAuthGroupMembershipInput,\n} from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport { cloneRecord, removeGroupMembershipRecord, upsertGroupMembershipRecord } from \"./shared\"\n\nexport class InMemoryAuthGroupMembershipStore implements AuthGroupMembershipStore {\n constructor(private readonly state: AuthStorageState) {}\n\n async upsert(input: UpsertAuthGroupMembershipInput): Promise<GroupMembershipRecord> {\n return cloneRecord(upsertGroupMembershipRecord(this.state, input))\n }\n\n async remove(params: {\n readonly projectId: string\n readonly userId: string\n readonly groupId: string\n }): Promise<GroupMembershipRecord | null> {\n const removed = removeGroupMembershipRecord(this.state, params)\n return removed ? cloneRecord(removed) : null\n }\n\n async listForUser(params: {\n readonly projectId: string\n readonly userId: string\n }): Promise<readonly GroupMembershipRecord[]> {\n return [...this.state.groupMemberships.values()]\n .filter((membership) => membership.projectId === params.projectId)\n .filter((membership) => membership.userId === params.userId)\n .sort((a, b) => a.groupId.localeCompare(b.groupId))\n .map(cloneRecord)\n }\n\n async listForGroup(params: {\n readonly projectId: string\n readonly groupId: string\n }): Promise<readonly GroupMembershipRecord[]> {\n return [...this.state.groupMemberships.values()]\n .filter((membership) => membership.projectId === params.projectId)\n .filter((membership) => membership.groupId === params.groupId)\n .sort((a, b) => a.userId.localeCompare(b.userId))\n .map(cloneRecord)\n }\n}\n",
|
|
22
|
+
"import type {\n AuthUserIdentityStore,\n UpsertAuthUserIdentityInput,\n UserIdentityRecord,\n} from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n assertNonEmpty,\n cloneOptionalRecord,\n cloneRecord,\n dateOrNow,\n identityKey,\n normalizeClaims,\n} from \"./shared\"\n\nexport class InMemoryAuthUserIdentityStore implements AuthUserIdentityStore {\n constructor(private readonly state: AuthStorageState) {}\n\n async upsert(input: UpsertAuthUserIdentityInput): Promise<UserIdentityRecord> {\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const strategyId = assertNonEmpty(input.strategyId, \"Strategy id\")\n const subject = assertNonEmpty(input.subject, \"Subject\")\n const userId = assertNonEmpty(input.userId, \"User id\")\n const key = identityKey(projectId, strategyId, subject)\n const existing = this.state.identities.get(key)\n const createdAt = existing?.createdAt ?? dateOrNow(input.createdAt)\n const identity: UserIdentityRecord = {\n projectId,\n strategyId,\n subject,\n userId,\n claims: normalizeClaims(input.claims),\n createdAt,\n updatedAt: input.updatedAt ? new Date(input.updatedAt) : existing ? new Date() : createdAt,\n }\n\n this.state.identities.set(key, cloneRecord(identity))\n return cloneRecord(identity)\n }\n\n async getBySubject(params: {\n readonly projectId: string\n readonly strategyId: string\n readonly subject: string\n }): Promise<UserIdentityRecord | null> {\n const record =\n this.state.identities.get(identityKey(params.projectId, params.strategyId, params.subject)) ??\n null\n return cloneOptionalRecord(record)\n }\n\n async listForUser(params: {\n readonly projectId: string\n readonly userId: string\n }): Promise<readonly UserIdentityRecord[]> {\n return [...this.state.identities.values()]\n .filter((identity) => identity.projectId === params.projectId)\n .filter((identity) => identity.userId === params.userId)\n .sort((a, b) => {\n const delta = a.createdAt.getTime() - b.createdAt.getTime()\n if (delta !== 0) return delta\n return `${a.strategyId}:${a.subject}`.localeCompare(`${b.strategyId}:${b.subject}`)\n })\n .map(cloneRecord)\n }\n}\n",
|
|
23
|
+
"export interface ListWindow {\n readonly limit?: number\n readonly offset?: number\n}\n\nexport interface ListPage<T> {\n readonly page: readonly T[]\n readonly total: number\n readonly hasMore: boolean\n}\n\nexport function paginate<T>(values: readonly T[], input: ListWindow): ListPage<T> {\n const offset = input.offset ?? 0\n const limit = input.limit ?? values.length\n const total = values.length\n const page = values.slice(offset, offset + limit)\n\n return {\n page,\n total,\n hasMore: offset + page.length < total,\n }\n}\n",
|
|
24
|
+
"import { paginate } from \"../../pagination\"\nimport { AuthStorageError } from \"../errors\"\nimport type {\n AuthInvitationStore,\n CreateOrUpdateAuthInvitationInput,\n InvitationRecord,\n ListAuthInvitationsInput,\n ListAuthInvitationsResult,\n} from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n assertNonEmpty,\n cloneDate,\n cloneOptionalRecord,\n cloneRecord,\n compareByCreatedAt,\n dateOrNow,\n getActiveInvitationByEmail,\n invitationKey,\n normalizeEmail,\n normalizeGroupIds,\n} from \"./shared\"\n\nexport class InMemoryAuthInvitationStore implements AuthInvitationStore {\n constructor(private readonly state: AuthStorageState) {}\n\n async createOrUpdateActive(input: CreateOrUpdateAuthInvitationInput): Promise<InvitationRecord> {\n const id = assertNonEmpty(input.id, \"Invitation id\")\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const email = normalizeEmail(input.email)\n const groupIds = normalizeGroupIds(input.groupIds)\n const now = dateOrNow(input.updatedAt ?? input.createdAt)\n const existingActive = getActiveInvitationByEmail(this.state, projectId, email, now)\n\n if (existingActive) {\n const next: InvitationRecord = {\n ...existingActive,\n groupIds,\n createdByPrincipal: input.createdByPrincipal,\n createdBySessionId: input.createdBySessionId,\n expiresAt: cloneDate(input.expiresAt),\n updatedAt: now,\n }\n this.state.invitations.set(invitationKey(projectId, existingActive.id), cloneRecord(next))\n return cloneRecord(next)\n }\n\n const key = invitationKey(projectId, id)\n if (this.state.invitations.has(key)) {\n throw new AuthStorageError(\n \"duplicate_invitation\",\n `[Sixb] Invitation '${id}' already exists but is not active for project '${projectId}'.`\n )\n }\n\n const invitation: InvitationRecord = {\n id,\n projectId,\n email,\n groupIds,\n status: \"pending\",\n createdByPrincipal: input.createdByPrincipal,\n createdBySessionId: input.createdBySessionId,\n createdAt: dateOrNow(input.createdAt),\n updatedAt: now,\n expiresAt: cloneDate(input.expiresAt),\n }\n this.state.invitations.set(key, cloneRecord(invitation))\n return cloneRecord(invitation)\n }\n\n async getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<InvitationRecord | null> {\n const record = this.state.invitations.get(invitationKey(params.projectId, params.id)) ?? null\n return cloneOptionalRecord(record)\n }\n\n async getActiveByEmail(params: {\n readonly projectId: string\n readonly email: string\n readonly now: Date\n }): Promise<InvitationRecord | null> {\n return cloneOptionalRecord(\n getActiveInvitationByEmail(this.state, params.projectId, params.email, params.now)\n )\n }\n\n async list(input: ListAuthInvitationsInput): Promise<ListAuthInvitationsResult> {\n if (input.statuses?.length === 0 || input.groupIds?.length === 0) {\n return { invitations: [], hasMore: false, total: 0 }\n }\n\n const statuses = input.statuses ? new Set(input.statuses) : null\n const groupIds = input.groupIds ? new Set(input.groupIds) : null\n const email = input.email ? normalizeEmail(input.email) : null\n const order = input.order ?? \"desc\"\n const invitations = [...this.state.invitations.values()]\n .filter((invitation) => invitation.projectId === input.projectId)\n .filter((invitation) => (email ? invitation.email === email : true))\n .filter((invitation) => (statuses ? statuses.has(invitation.status) : true))\n .filter((invitation) =>\n groupIds ? invitation.groupIds.some((groupId) => groupIds.has(groupId)) : true\n )\n .sort((a, b) => compareByCreatedAt(a, b, order))\n\n const page = paginate(invitations, input)\n return {\n invitations: page.page.map(cloneRecord),\n hasMore: page.hasMore,\n total: page.total,\n }\n }\n\n async accept(params: {\n readonly projectId: string\n readonly id: string\n readonly acceptedAt: Date\n }): Promise<InvitationRecord> {\n const key = invitationKey(params.projectId, params.id)\n const existing = this.state.invitations.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_invitation\",\n `[Sixb] Invitation '${params.id}' not found for project '${params.projectId}'.`\n )\n }\n\n const next: InvitationRecord = {\n ...existing,\n status: \"accepted\",\n acceptedAt: cloneDate(params.acceptedAt),\n updatedAt: cloneDate(params.acceptedAt),\n }\n this.state.invitations.set(key, cloneRecord(next))\n return cloneRecord(next)\n }\n\n async revoke(params: {\n readonly projectId: string\n readonly id: string\n readonly revokedAt: Date\n }): Promise<InvitationRecord> {\n const key = invitationKey(params.projectId, params.id)\n const existing = this.state.invitations.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_invitation\",\n `[Sixb] Invitation '${params.id}' not found for project '${params.projectId}'.`\n )\n }\n\n const next: InvitationRecord = {\n ...existing,\n status: \"revoked\",\n revokedAt: cloneDate(params.revokedAt),\n updatedAt: cloneDate(params.revokedAt),\n }\n this.state.invitations.set(key, cloneRecord(next))\n return cloneRecord(next)\n }\n}\n",
|
|
25
|
+
"import { resolveAuthSessionAudience } from \"../../../auth/audience\"\nimport { AuthStorageError } from \"../errors\"\nimport type { AuthMagicLinkStore, CreateAuthMagicLinkInput, MagicLinkRecord } from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n assertNonEmpty,\n cloneDate,\n cloneOptionalRecord,\n cloneRecord,\n compareByCreatedAt,\n consumeMagicLinkRecord,\n isActiveMagicLink,\n magicLinkKey,\n normalizeEmail,\n revokeActiveMagicLinksForEmail,\n} from \"./shared\"\n\nexport class InMemoryAuthMagicLinkStore implements AuthMagicLinkStore {\n constructor(private readonly state: AuthStorageState) {}\n\n async create(input: CreateAuthMagicLinkInput): Promise<MagicLinkRecord> {\n const id = assertNonEmpty(input.id, \"Magic link id\")\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const strategyId = assertNonEmpty(input.strategyId, \"Strategy id\")\n const audience = resolveAuthSessionAudience(input.audience)\n const email = normalizeEmail(input.email)\n const tokenHash = assertNonEmpty(input.tokenHash, \"Magic link token hash\")\n const key = magicLinkKey(projectId, id)\n\n if (this.state.magicLinks.has(key)) {\n throw new AuthStorageError(\n \"duplicate_magic_link\",\n `[Sixb] Magic link '${id}' already exists for project '${projectId}'.`\n )\n }\n\n revokeActiveMagicLinksForEmail(this.state, projectId, email, input.createdAt)\n\n const link: MagicLinkRecord = {\n id,\n projectId,\n strategyId,\n audience,\n email,\n tokenHash,\n returnTo: input.returnTo,\n createdAt: cloneDate(input.createdAt),\n expiresAt: cloneDate(input.expiresAt),\n }\n this.state.magicLinks.set(key, cloneRecord(link))\n return cloneRecord(link)\n }\n\n async getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<MagicLinkRecord | null> {\n const record = this.state.magicLinks.get(magicLinkKey(params.projectId, params.id)) ?? null\n return cloneOptionalRecord(record)\n }\n\n async getActiveByEmail(params: {\n readonly projectId: string\n readonly email: string\n readonly now: Date\n }): Promise<MagicLinkRecord | null> {\n const email = normalizeEmail(params.email)\n const links = [...this.state.magicLinks.values()]\n .filter((link) => link.projectId === params.projectId)\n .filter((link) => link.email === email)\n .filter((link) => isActiveMagicLink(link, params.now))\n .sort((a, b) => compareByCreatedAt(a, b, \"desc\"))\n\n return cloneOptionalRecord(links[0] ?? null)\n }\n\n async consume(params: {\n readonly projectId: string\n readonly id: string\n readonly tokenHash: string\n readonly consumedAt: Date\n }): Promise<MagicLinkRecord> {\n return cloneRecord(consumeMagicLinkRecord(this.state, params))\n }\n\n async revokeActiveForEmail(params: {\n readonly projectId: string\n readonly email: string\n readonly revokedAt: Date\n }): Promise<readonly MagicLinkRecord[]> {\n return revokeActiveMagicLinksForEmail(\n this.state,\n params.projectId,\n params.email,\n params.revokedAt\n ).map(cloneRecord)\n }\n}\n",
|
|
26
|
+
"import { resolveAuthSessionAudience } from \"../../../auth/audience\"\nimport { AuthStorageError } from \"../errors\"\nimport type {\n AuthOidcAuthorizationAttemptStore,\n CreateOidcAuthorizationAttemptInput,\n OidcAuthorizationAttemptRecord,\n} from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n assertNonEmpty,\n cloneDate,\n cloneOptionalRecord,\n cloneRecord,\n consumeOidcAttemptRecord,\n oidcAttemptKey,\n} from \"./shared\"\n\nexport class InMemoryAuthOidcAuthorizationAttemptStore\n implements AuthOidcAuthorizationAttemptStore\n{\n constructor(private readonly state: AuthStorageState) {}\n\n async create(\n input: CreateOidcAuthorizationAttemptInput\n ): Promise<OidcAuthorizationAttemptRecord> {\n const id = assertNonEmpty(input.id, \"OIDC authorization attempt id\")\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const strategyId = assertNonEmpty(input.strategyId, \"Strategy id\")\n const audience = resolveAuthSessionAudience(input.audience)\n const stateHash = assertNonEmpty(input.stateHash, \"OIDC state hash\")\n const nonceHash = assertNonEmpty(input.nonceHash, \"OIDC nonce hash\")\n const codeVerifier = assertNonEmpty(input.codeVerifier, \"OIDC code verifier\")\n const key = oidcAttemptKey(projectId, id)\n\n if (this.state.oidcAuthorizationAttempts.has(key)) {\n throw new AuthStorageError(\n \"duplicate_oidc_attempt\",\n `[Sixb] OIDC authorization attempt '${id}' already exists for project '${projectId}'.`\n )\n }\n\n const attempt: OidcAuthorizationAttemptRecord = {\n id,\n projectId,\n strategyId,\n audience,\n stateHash,\n nonceHash,\n codeVerifier,\n returnTo: input.returnTo,\n createdAt: cloneDate(input.createdAt),\n expiresAt: cloneDate(input.expiresAt),\n }\n this.state.oidcAuthorizationAttempts.set(key, cloneRecord(attempt))\n return cloneRecord(attempt)\n }\n\n async getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<OidcAuthorizationAttemptRecord | null> {\n const record =\n this.state.oidcAuthorizationAttempts.get(oidcAttemptKey(params.projectId, params.id)) ?? null\n return cloneOptionalRecord(record)\n }\n\n async consume(params: {\n readonly projectId: string\n readonly id: string\n readonly stateHash: string\n readonly consumedAt: Date\n }): Promise<OidcAuthorizationAttemptRecord> {\n return cloneRecord(consumeOidcAttemptRecord(this.state, params))\n }\n}\n",
|
|
27
|
+
"import { AuthStorageError } from \"../errors\"\nimport type {\n AuthServiceAccountGroupMembershipStore,\n ReconcileAuthServiceAccountGroupMembershipsInput,\n ServiceAccountGroupMembershipRecord,\n UpsertAuthServiceAccountGroupMembershipInput,\n} from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n assertNonEmpty,\n cloneRecord,\n dateOrNow,\n normalizeGroupIds,\n serviceAccountGroupMembershipKey,\n serviceAccountKey,\n upsertServiceAccountGroupMembershipRecord,\n} from \"./shared\"\n\nexport class InMemoryAuthServiceAccountGroupMembershipStore\n implements AuthServiceAccountGroupMembershipStore\n{\n constructor(private readonly state: AuthStorageState) {}\n\n async upsert(\n input: UpsertAuthServiceAccountGroupMembershipInput\n ): Promise<ServiceAccountGroupMembershipRecord> {\n return cloneRecord(upsertServiceAccountGroupMembershipRecord(this.state, input))\n }\n\n async reconcileForServiceAccount(\n input: ReconcileAuthServiceAccountGroupMembershipsInput\n ): Promise<readonly ServiceAccountGroupMembershipRecord[]> {\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const serviceAccountId = assertNonEmpty(input.serviceAccountId, \"Service account id\")\n if (!this.state.serviceAccounts.has(serviceAccountKey(projectId, serviceAccountId))) {\n throw new AuthStorageError(\n \"missing_service_account\",\n `[Sixb] Service account '${serviceAccountId}' not found for project '${projectId}'.`\n )\n }\n\n const groupIds = normalizeGroupIds(input.groupIds)\n const desired = new Set(groupIds)\n for (const [key, membership] of this.state.serviceAccountGroupMemberships) {\n if (\n membership.projectId === projectId &&\n membership.serviceAccountId === serviceAccountId &&\n membership.source === input.source &&\n !desired.has(membership.groupId)\n ) {\n this.state.serviceAccountGroupMemberships.delete(key)\n }\n }\n\n const updatedAt = dateOrNow(input.updatedAt)\n for (const groupId of groupIds) {\n const key = serviceAccountGroupMembershipKey(projectId, serviceAccountId, groupId)\n const existing = this.state.serviceAccountGroupMemberships.get(key)\n if (existing) {\n this.state.serviceAccountGroupMemberships.set(\n key,\n cloneRecord({ ...existing, source: input.source })\n )\n continue\n }\n this.state.serviceAccountGroupMemberships.set(\n key,\n cloneRecord({\n projectId,\n serviceAccountId,\n groupId,\n source: input.source,\n createdAt: updatedAt,\n })\n )\n }\n\n return this.listForServiceAccount({ projectId, serviceAccountId })\n }\n\n async listForServiceAccount(params: {\n readonly projectId: string\n readonly serviceAccountId: string\n }): Promise<readonly ServiceAccountGroupMembershipRecord[]> {\n return [...this.state.serviceAccountGroupMemberships.values()]\n .filter((membership) => membership.projectId === params.projectId)\n .filter((membership) => membership.serviceAccountId === params.serviceAccountId)\n .sort((a, b) => a.groupId.localeCompare(b.groupId))\n .map(cloneRecord)\n }\n\n async listForGroup(params: {\n readonly projectId: string\n readonly groupId: string\n }): Promise<readonly ServiceAccountGroupMembershipRecord[]> {\n return [...this.state.serviceAccountGroupMemberships.values()]\n .filter((membership) => membership.projectId === params.projectId)\n .filter((membership) => membership.groupId === params.groupId)\n .sort((a, b) => a.serviceAccountId.localeCompare(b.serviceAccountId))\n .map(cloneRecord)\n }\n}\n",
|
|
28
|
+
"import { AuthStorageError } from \"../errors\"\nimport type {\n AuthServiceAccountStore,\n CreateAuthServiceAccountInput,\n ListAuthServiceAccountsInput,\n ListAuthServiceAccountsResult,\n ServiceAccountRecord,\n UpdateAuthServiceAccountInput,\n} from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n assertNonEmpty,\n cloneDate,\n cloneOptionalRecord,\n cloneRecord,\n compareByCreatedAt,\n createServiceAccountRecord,\n serviceAccountKey,\n} from \"./shared\"\n\nexport class InMemoryAuthServiceAccountStore implements AuthServiceAccountStore {\n constructor(private readonly state: AuthStorageState) {}\n\n async create(input: CreateAuthServiceAccountInput): Promise<ServiceAccountRecord> {\n return cloneRecord(createServiceAccountRecord(this.state, input))\n }\n\n async getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<ServiceAccountRecord | null> {\n const record =\n this.state.serviceAccounts.get(serviceAccountKey(params.projectId, params.id)) ?? null\n return cloneOptionalRecord(record)\n }\n\n async update(input: UpdateAuthServiceAccountInput): Promise<ServiceAccountRecord> {\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const id = assertNonEmpty(input.id, \"Service account id\")\n const key = serviceAccountKey(projectId, id)\n const existing = this.state.serviceAccounts.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_service_account\",\n `[Sixb] Service account '${id}' not found for project '${projectId}'.`\n )\n }\n\n const next: ServiceAccountRecord = {\n ...existing,\n name:\n input.name === undefined\n ? existing.name\n : assertNonEmpty(input.name, \"Service account name\"),\n description: input.description === undefined ? existing.description : input.description,\n status: input.status ?? existing.status,\n updatedAt: input.updatedAt ? cloneDate(input.updatedAt) : new Date(),\n }\n this.state.serviceAccounts.set(key, cloneRecord(next))\n return cloneRecord(next)\n }\n\n async list(input: ListAuthServiceAccountsInput): Promise<ListAuthServiceAccountsResult> {\n const statuses = input.statuses ? new Set(input.statuses) : null\n const order = input.order ?? \"asc\"\n const offset = input.offset ?? 0\n const rows = [...this.state.serviceAccounts.values()]\n .filter((serviceAccount) => serviceAccount.projectId === input.projectId)\n .filter((serviceAccount) => !statuses || statuses.has(serviceAccount.status))\n .sort((a, b) => compareByCreatedAt(a, b, order))\n const page = rows.slice(offset, input.limit === undefined ? undefined : offset + input.limit)\n\n return {\n serviceAccounts: page.map(cloneRecord),\n hasMore: input.limit === undefined ? false : offset + input.limit < rows.length,\n total: rows.length,\n }\n }\n}\n",
|
|
29
|
+
"import type { AuthSessionAudience } from \"../../../auth/audience\"\nimport { AuthStorageError } from \"../errors\"\nimport type { AuthSessionStore, CreateAuthSessionInput, SessionRecord } from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n cloneDate,\n cloneOptionalRecord,\n cloneRecord,\n compareByCreatedAt,\n createSessionRecord,\n isActiveSession,\n revokeActiveSessionsForUser,\n sessionKey,\n} from \"./shared\"\n\nexport class InMemoryAuthSessionStore implements AuthSessionStore {\n constructor(private readonly state: AuthStorageState) {}\n\n async create(input: CreateAuthSessionInput): Promise<SessionRecord> {\n return cloneRecord(createSessionRecord(this.state, input))\n }\n\n async getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<SessionRecord | null> {\n const record = this.state.sessions.get(sessionKey(params.projectId, params.id)) ?? null\n return cloneOptionalRecord(record)\n }\n\n async getActiveByUserId(params: {\n readonly projectId: string\n readonly userId: string\n readonly audience: AuthSessionAudience\n readonly now: Date\n }): Promise<SessionRecord | null> {\n const sessions = [...this.state.sessions.values()]\n .filter((session) => session.projectId === params.projectId)\n .filter((session) => session.userId === params.userId)\n .filter((session) => session.audience === params.audience)\n .filter((session) => isActiveSession(session, params.now))\n .sort((a, b) => compareByCreatedAt(a, b, \"desc\"))\n\n return cloneOptionalRecord(sessions[0] ?? null)\n }\n\n async listActiveByUserId(params: {\n readonly projectId: string\n readonly userId: string\n readonly now: Date\n }): Promise<readonly SessionRecord[]> {\n return [...this.state.sessions.values()]\n .filter((session) => session.projectId === params.projectId)\n .filter((session) => session.userId === params.userId)\n .filter((session) => isActiveSession(session, params.now))\n .sort((a, b) => {\n const activity =\n (b.lastSeenAt ?? b.createdAt).getTime() - (a.lastSeenAt ?? a.createdAt).getTime()\n if (activity !== 0) return activity\n const created = b.createdAt.getTime() - a.createdAt.getTime()\n return created !== 0 ? created : b.id.localeCompare(a.id)\n })\n .map(cloneRecord)\n }\n\n async findValidByTokenHash(params: {\n readonly projectId: string\n readonly id: string\n readonly audience: AuthSessionAudience\n readonly tokenHash: string\n readonly now: Date\n }): Promise<SessionRecord | null> {\n const session = this.state.sessions.get(sessionKey(params.projectId, params.id))\n if (\n !session ||\n session.audience !== params.audience ||\n session.tokenHash !== params.tokenHash ||\n !isActiveSession(session, params.now)\n ) {\n return null\n }\n\n return cloneRecord(session)\n }\n\n async renewIfValid(params: {\n readonly projectId: string\n readonly id: string\n readonly audience: AuthSessionAudience\n readonly tokenHash: string\n readonly now: Date\n readonly expiresAt: Date\n }): Promise<SessionRecord | null> {\n const key = sessionKey(params.projectId, params.id)\n const session = this.state.sessions.get(key)\n if (\n !session ||\n session.audience !== params.audience ||\n session.tokenHash !== params.tokenHash ||\n !isActiveSession(session, params.now)\n ) {\n return null\n }\n\n const requestedExpiresAt = session.absoluteExpiresAt\n ? new Date(Math.min(params.expiresAt.getTime(), session.absoluteExpiresAt.getTime()))\n : params.expiresAt\n const next: SessionRecord = {\n ...session,\n expiresAt: new Date(Math.max(session.expiresAt.getTime(), requestedExpiresAt.getTime())),\n lastSeenAt: cloneDate(params.now),\n }\n this.state.sessions.set(key, cloneRecord(next))\n return cloneRecord(next)\n }\n\n async revoke(params: {\n readonly projectId: string\n readonly id: string\n readonly revokedAt: Date\n }): Promise<SessionRecord> {\n const key = sessionKey(params.projectId, params.id)\n const existing = this.state.sessions.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_session\",\n `[Sixb] Session '${params.id}' not found for project '${params.projectId}'.`\n )\n }\n\n const next: SessionRecord = {\n ...existing,\n revokedAt: cloneDate(params.revokedAt),\n }\n this.state.sessions.set(key, cloneRecord(next))\n return cloneRecord(next)\n }\n\n async revokeActiveForUser(params: {\n readonly projectId: string\n readonly userId: string\n readonly audience?: AuthSessionAudience\n readonly revokedAt: Date\n }): Promise<readonly SessionRecord[]> {\n return revokeActiveSessionsForUser(\n this.state,\n params.projectId,\n params.userId,\n params.revokedAt,\n params.audience\n ).map(cloneRecord)\n }\n\n async touch(params: {\n readonly projectId: string\n readonly id: string\n readonly lastSeenAt: Date\n }): Promise<SessionRecord> {\n const key = sessionKey(params.projectId, params.id)\n const existing = this.state.sessions.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_session\",\n `[Sixb] Session '${params.id}' not found for project '${params.projectId}'.`\n )\n }\n\n const next: SessionRecord = {\n ...existing,\n lastSeenAt: cloneDate(params.lastSeenAt),\n }\n this.state.sessions.set(key, cloneRecord(next))\n return cloneRecord(next)\n }\n}\n",
|
|
30
|
+
"import { paginate } from \"../../pagination\"\nimport { AuthStorageError } from \"../errors\"\nimport type {\n AuthUserStore,\n CreateAuthUserInput,\n ListAuthUsersInput,\n ListAuthUsersResult,\n UpdateAuthUserProfileInput,\n UpdateAuthUserStatusInput,\n UserRecord,\n} from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n assertNonEmpty,\n cloneDate,\n cloneOptionalRecord,\n cloneRecord,\n compareByCreatedAt,\n dateOrNow,\n getUserByEmail,\n normalizeEmail,\n userKey,\n} from \"./shared\"\n\nexport class InMemoryAuthUserStore implements AuthUserStore {\n constructor(private readonly state: AuthStorageState) {}\n\n async create(input: CreateAuthUserInput): Promise<UserRecord> {\n const id = assertNonEmpty(input.id, \"User id\")\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const email = normalizeEmail(input.email)\n const key = userKey(projectId, id)\n\n if (this.state.users.has(key)) {\n throw new AuthStorageError(\n \"duplicate_user\",\n `[Sixb] User '${id}' already exists for project '${projectId}'.`\n )\n }\n\n if (getUserByEmail(this.state, projectId, email)) {\n throw new AuthStorageError(\n \"duplicate_user\",\n `[Sixb] User email '${email}' already exists for project '${projectId}'.`\n )\n }\n\n const createdAt = dateOrNow(input.createdAt)\n const user: UserRecord = {\n id,\n projectId,\n email,\n displayName: input.displayName,\n avatarUrl: input.avatarUrl,\n status: input.status ?? \"active\",\n createdAt,\n updatedAt: input.updatedAt ? cloneDate(input.updatedAt) : cloneDate(createdAt),\n }\n\n this.state.users.set(key, cloneRecord(user))\n return cloneRecord(user)\n }\n\n async getById(params: {\n readonly projectId: string\n readonly id: string\n }): Promise<UserRecord | null> {\n const record = this.state.users.get(userKey(params.projectId, params.id)) ?? null\n return cloneOptionalRecord(record)\n }\n\n async getByEmail(params: {\n readonly projectId: string\n readonly email: string\n }): Promise<UserRecord | null> {\n return cloneOptionalRecord(getUserByEmail(this.state, params.projectId, params.email))\n }\n\n async updateProfile(input: UpdateAuthUserProfileInput): Promise<UserRecord> {\n const key = userKey(input.projectId, input.id)\n const existing = this.state.users.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_user\",\n `[Sixb] User '${input.id}' not found for project '${input.projectId}'.`\n )\n }\n\n const next: UserRecord = {\n ...existing,\n displayName: input.displayName,\n avatarUrl: input.avatarUrl,\n updatedAt: dateOrNow(input.updatedAt),\n }\n this.state.users.set(key, cloneRecord(next))\n return cloneRecord(next)\n }\n\n async updateStatus(input: UpdateAuthUserStatusInput): Promise<UserRecord> {\n const key = userKey(input.projectId, input.id)\n const existing = this.state.users.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_user\",\n `[Sixb] User '${input.id}' not found for project '${input.projectId}'.`\n )\n }\n\n const next: UserRecord = {\n ...existing,\n status: input.status,\n updatedAt: dateOrNow(input.updatedAt),\n }\n this.state.users.set(key, cloneRecord(next))\n return cloneRecord(next)\n }\n\n async list(input: ListAuthUsersInput): Promise<ListAuthUsersResult> {\n if (input.statuses?.length === 0) {\n return { users: [], hasMore: false, total: 0 }\n }\n\n const statuses = input.statuses ? new Set(input.statuses) : null\n const order = input.order ?? \"desc\"\n const rows = [...this.state.users.values()]\n .filter((user) => user.projectId === input.projectId)\n .filter((user) => (statuses ? statuses.has(user.status) : true))\n .sort((a, b) => compareByCreatedAt(a, b, order))\n\n const page = paginate(rows, input)\n return {\n users: page.page.map(cloneRecord),\n hasMore: page.hasMore,\n total: page.total,\n }\n }\n}\n",
|
|
31
|
+
"import { AuthStorageError } from \"../errors\"\nimport type {\n AuthStorage,\n CompleteDeviceAuthorizationInput,\n CompleteDeviceAuthorizationResult,\n CompleteMagicLinkSignInInput,\n CompleteOidcSignInInput,\n CompleteSignInResult,\n GroupMembershipRecord,\n InvitationRecord,\n SessionRecord,\n SuspendUserAndRevokeSessionsInput,\n UserIdentityRecord,\n UserRecord,\n} from \"../types\"\nimport { InMemoryAuthAccessTokenStore } from \"./access-tokens\"\nimport { InMemoryAuthDeviceAuthorizationStore } from \"./device-authorizations\"\nimport { InMemoryAuthGroupMembershipStore } from \"./group-memberships\"\nimport { InMemoryAuthUserIdentityStore } from \"./identities\"\nimport { InMemoryAuthInvitationStore } from \"./invitations\"\nimport { InMemoryAuthMagicLinkStore } from \"./magic-links\"\nimport { InMemoryAuthOidcAuthorizationAttemptStore } from \"./oidc-attempts\"\nimport { InMemoryAuthServiceAccountGroupMembershipStore } from \"./service-account-group-memberships\"\nimport { InMemoryAuthServiceAccountStore } from \"./service-accounts\"\nimport { InMemoryAuthSessionStore } from \"./sessions\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n assertNonEmpty,\n cloneDate,\n cloneRecord,\n consumeMagicLinkRecord,\n consumeOidcAttemptRecord,\n createAccessTokenRecord,\n createAuthStorageState,\n createSessionRecord,\n deviceAuthorizationKey,\n getActiveInvitationByEmail,\n getUserByEmail,\n identityKey,\n invitationKey,\n magicLinkKey,\n normalizeClaims,\n normalizeEmail,\n normalizeGroupIds,\n oidcAttemptKey,\n revokeActiveSessionsForUser,\n upsertGroupMembershipRecord,\n userKey,\n validateCompleteSessionInput,\n} from \"./shared\"\nimport { InMemoryAuthUserStore } from \"./users\"\n\nexport class InMemoryAuthStorage implements AuthStorage {\n private readonly state: AuthStorageState = createAuthStorageState()\n\n readonly users = new InMemoryAuthUserStore(this.state)\n readonly identities = new InMemoryAuthUserIdentityStore(this.state)\n readonly serviceAccounts = new InMemoryAuthServiceAccountStore(this.state)\n readonly serviceAccountGroupMemberships = new InMemoryAuthServiceAccountGroupMembershipStore(\n this.state\n )\n readonly sessions = new InMemoryAuthSessionStore(this.state)\n readonly accessTokens = new InMemoryAuthAccessTokenStore(this.state)\n readonly invitations = new InMemoryAuthInvitationStore(this.state)\n readonly groupMemberships = new InMemoryAuthGroupMembershipStore(this.state)\n readonly magicLinks = new InMemoryAuthMagicLinkStore(this.state)\n readonly oidcAuthorizationAttempts = new InMemoryAuthOidcAuthorizationAttemptStore(this.state)\n readonly deviceAuthorizations = new InMemoryAuthDeviceAuthorizationStore(this.state)\n\n snapshot(): InMemoryAuthStorageSnapshot {\n return {\n users: structuredClone(this.state.users),\n identities: structuredClone(this.state.identities),\n serviceAccounts: structuredClone(this.state.serviceAccounts),\n serviceAccountGroupMemberships: structuredClone(this.state.serviceAccountGroupMemberships),\n sessions: structuredClone(this.state.sessions),\n accessTokens: structuredClone(this.state.accessTokens),\n invitations: structuredClone(this.state.invitations),\n groupMemberships: structuredClone(this.state.groupMemberships),\n magicLinks: structuredClone(this.state.magicLinks),\n oidcAuthorizationAttempts: structuredClone(this.state.oidcAuthorizationAttempts),\n deviceAuthorizations: structuredClone(this.state.deviceAuthorizations),\n }\n }\n\n restore(snapshot: InMemoryAuthStorageSnapshot): void {\n restoreMap(this.state.users, snapshot.users)\n restoreMap(this.state.identities, snapshot.identities)\n restoreMap(this.state.serviceAccounts, snapshot.serviceAccounts)\n restoreMap(this.state.serviceAccountGroupMemberships, snapshot.serviceAccountGroupMemberships)\n restoreMap(this.state.sessions, snapshot.sessions)\n restoreMap(this.state.accessTokens, snapshot.accessTokens)\n restoreMap(this.state.invitations, snapshot.invitations)\n restoreMap(this.state.groupMemberships, snapshot.groupMemberships)\n restoreMap(this.state.magicLinks, snapshot.magicLinks)\n restoreMap(this.state.oidcAuthorizationAttempts, snapshot.oidcAuthorizationAttempts)\n restoreMap(this.state.deviceAuthorizations, snapshot.deviceAuthorizations)\n }\n\n async completeDeviceAuthorization(\n input: CompleteDeviceAuthorizationInput\n ): Promise<CompleteDeviceAuthorizationResult> {\n const key = deviceAuthorizationKey(input.projectId, input.id)\n const authorization = this.state.deviceAuthorizations.get(key)\n if (!authorization) {\n throw new AuthStorageError(\n \"missing_device_authorization\",\n `[Sixb] Device authorization '${input.id}' not found for project '${input.projectId}'.`\n )\n }\n if (authorization.deviceCodeHash !== input.deviceCodeHash) {\n throw new AuthStorageError(\n \"invalid_device_authorization\",\n \"[Sixb] Invalid device authorization.\"\n )\n }\n if (authorization.status === \"pending\") {\n throw new AuthStorageError(\n \"pending_device_authorization\",\n \"[Sixb] Device authorization is pending.\"\n )\n }\n if (authorization.status === \"denied\") {\n throw new AuthStorageError(\n \"device_authorization_denied\",\n \"[Sixb] Device authorization was denied.\"\n )\n }\n if (\n authorization.status !== \"approved\" ||\n !authorization.approvedUserId ||\n !authorization.approvedSessionId ||\n authorization.expiresAt <= input.completedAt\n ) {\n throw new AuthStorageError(\n \"invalid_device_authorization\",\n \"[Sixb] Device authorization is invalid.\"\n )\n }\n if (\n input.accessToken.projectId !== input.projectId ||\n input.accessToken.subjectType !== \"user\" ||\n input.accessToken.subjectId !== authorization.approvedUserId ||\n input.accessToken.createdBySessionId !== authorization.approvedSessionId\n ) {\n throw new AuthStorageError(\n \"invalid_device_authorization\",\n \"[Sixb] Device access token is invalid.\"\n )\n }\n const accessToken = createAccessTokenRecord(this.state, input.accessToken)\n const consumed = {\n ...authorization,\n status: \"consumed\" as const,\n consumedAt: new Date(input.completedAt),\n }\n this.state.deviceAuthorizations.set(key, cloneRecord(consumed))\n return { authorization: cloneRecord(consumed), accessToken: cloneRecord(accessToken) }\n }\n\n async completeMagicLinkSignIn(\n input: CompleteMagicLinkSignInInput\n ): Promise<CompleteSignInResult> {\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const completedAt = cloneDate(input.completedAt)\n const magicLink = this.state.magicLinks.get(magicLinkKey(projectId, input.magicLinkId))\n\n if (!magicLink) {\n throw new AuthStorageError(\n \"missing_magic_link\",\n `[Sixb] Magic link '${input.magicLinkId}' not found for project '${projectId}'.`\n )\n }\n\n if (magicLink.tokenHash !== input.tokenHash || magicLink.consumedAt || magicLink.revokedAt) {\n throw new AuthStorageError(\n \"invalid_magic_link\",\n `[Sixb] Magic link '${input.magicLinkId}' is not valid for project '${projectId}'.`\n )\n }\n\n if (magicLink.expiresAt <= completedAt) {\n throw new AuthStorageError(\n \"expired_magic_link\",\n `[Sixb] Magic link '${input.magicLinkId}' is expired for project '${projectId}'.`\n )\n }\n\n const existingUser = getUserByEmail(this.state, projectId, magicLink.email)\n const activeInvitation = getActiveInvitationByEmail(\n this.state,\n projectId,\n magicLink.email,\n completedAt\n )\n const shouldCreateUser = !existingUser\n const manualGroupIds = normalizeGroupIds(input.manualGroupIds)\n\n if (existingUser?.status === \"suspended\") {\n consumeMagicLinkRecord(this.state, {\n projectId,\n id: input.magicLinkId,\n tokenHash: input.tokenHash,\n consumedAt: completedAt,\n })\n throw new AuthStorageError(\n \"suspended_user\",\n `[Sixb] User '${existingUser.id}' is suspended for project '${projectId}'.`\n )\n }\n\n if (shouldCreateUser && !activeInvitation && !input.allowUserCreationWithoutInvitation) {\n consumeMagicLinkRecord(this.state, {\n projectId,\n id: input.magicLinkId,\n tokenHash: input.tokenHash,\n consumedAt: completedAt,\n })\n throw new AuthStorageError(\n \"user_creation_not_allowed\",\n `[Sixb] Magic link '${input.magicLinkId}' cannot create a user for project '${projectId}'.`\n )\n }\n\n if (\n shouldCreateUser &&\n !activeInvitation &&\n input.allowUserCreationWithoutInvitation &&\n input.requireNoActiveUsersForUserCreation &&\n hasActiveUsers(this.state, projectId)\n ) {\n consumeMagicLinkRecord(this.state, {\n projectId,\n id: input.magicLinkId,\n tokenHash: input.tokenHash,\n consumedAt: completedAt,\n })\n throw new AuthStorageError(\n \"user_creation_not_allowed\",\n `[Sixb] Magic link '${input.magicLinkId}' cannot create a user for project '${projectId}'.`\n )\n }\n\n validateCompleteSessionInput(this.state, projectId, input.session)\n assertSignInSessionAudience(projectId, input.session.audience, magicLink.audience)\n\n let newUserId: string | undefined\n if (shouldCreateUser) {\n newUserId = assertNonEmpty(input.newUserId, \"User id\")\n if (this.state.users.has(userKey(projectId, newUserId))) {\n throw new AuthStorageError(\n \"duplicate_user\",\n `[Sixb] User '${newUserId}' already exists for project '${projectId}'.`\n )\n }\n }\n\n consumeMagicLinkRecord(this.state, {\n projectId,\n id: input.magicLinkId,\n tokenHash: input.tokenHash,\n consumedAt: completedAt,\n })\n\n let user = existingUser\n if (!user) {\n user = {\n id: newUserId ?? assertNonEmpty(input.newUserId, \"User id\"),\n projectId,\n email: magicLink.email,\n displayName: input.newUserDisplayName,\n avatarUrl: input.newUserAvatarUrl,\n status: \"active\",\n createdAt: completedAt,\n updatedAt: completedAt,\n }\n this.state.users.set(userKey(projectId, user.id), cloneRecord(user))\n }\n\n const invitation = this.acceptInvitationAndApplyGroups({\n activeInvitation,\n completedAt,\n projectId,\n user,\n })\n const memberships = this.applyManualGroups({\n completedAt,\n groupIds: manualGroupIds,\n projectId,\n userId: user.id,\n existing: invitation.memberships,\n })\n\n const session = this.createSignInSession({\n projectId,\n strategyId: magicLink.strategyId,\n session: input.session,\n userId: user.id,\n })\n\n return {\n user: cloneRecord(user),\n session: cloneRecord(session),\n invitation: invitation.invitation ? cloneRecord(invitation.invitation) : undefined,\n groupMemberships: memberships.map(cloneRecord),\n }\n }\n\n async completeOidcSignIn(input: CompleteOidcSignInInput): Promise<CompleteSignInResult> {\n const projectId = assertNonEmpty(input.projectId, \"Project id\")\n const completedAt = cloneDate(input.completedAt)\n const attempt = this.state.oidcAuthorizationAttempts.get(\n oidcAttemptKey(projectId, input.oidcAuthorizationAttemptId)\n )\n\n if (!attempt) {\n throw new AuthStorageError(\n \"missing_oidc_attempt\",\n `[Sixb] OIDC authorization attempt '${input.oidcAuthorizationAttemptId}' not found for project '${projectId}'.`\n )\n }\n\n if (attempt.stateHash !== input.stateHash || attempt.consumedAt) {\n throw new AuthStorageError(\n \"invalid_oidc_attempt\",\n `[Sixb] OIDC authorization attempt '${input.oidcAuthorizationAttemptId}' is not valid for project '${projectId}'.`\n )\n }\n\n if (attempt.expiresAt <= completedAt) {\n throw new AuthStorageError(\n \"expired_oidc_attempt\",\n `[Sixb] OIDC authorization attempt '${input.oidcAuthorizationAttemptId}' is expired for project '${projectId}'.`\n )\n }\n\n const subject = assertNonEmpty(input.subject, \"Subject\")\n const email = normalizeEmail(input.email)\n const claims = normalizeClaims(input.claims)\n const identity = this.state.identities.get(identityKey(projectId, attempt.strategyId, subject))\n const activeInvitation = identity\n ? null\n : getActiveInvitationByEmail(this.state, projectId, email, completedAt)\n let user = identity\n ? (this.state.users.get(userKey(projectId, identity.userId)) ?? null)\n : getUserByEmail(this.state, projectId, email)\n const shouldCreateUser = !identity && !user\n const manualGroupIds = normalizeGroupIds(input.manualGroupIds)\n\n if (identity && !user) {\n this.consumeOidcAttempt(input, completedAt, projectId)\n throw new AuthStorageError(\n \"missing_user\",\n `[Sixb] User '${identity.userId}' not found for linked OIDC identity.`\n )\n }\n\n if (!identity && user && (!input.autoLinkByVerifiedEmail || !input.emailVerified)) {\n this.consumeOidcAttempt(input, completedAt, projectId)\n throw new AuthStorageError(\n \"email_link_not_allowed\",\n `[Sixb] OIDC identity cannot auto-link to user '${user.id}' for project '${projectId}'.`\n )\n }\n\n if (user?.status === \"suspended\") {\n this.consumeOidcAttempt(input, completedAt, projectId)\n throw new AuthStorageError(\n \"suspended_user\",\n `[Sixb] User '${user.id}' is suspended for project '${projectId}'.`\n )\n }\n\n if (shouldCreateUser && !input.emailVerified) {\n this.consumeOidcAttempt(input, completedAt, projectId)\n throw new AuthStorageError(\n \"user_creation_not_allowed\",\n `[Sixb] OIDC authorization attempt '${input.oidcAuthorizationAttemptId}' cannot create a user for project '${projectId}'.`\n )\n }\n\n if (shouldCreateUser && !activeInvitation && !input.allowUserCreationWithoutInvitation) {\n this.consumeOidcAttempt(input, completedAt, projectId)\n throw new AuthStorageError(\n \"user_creation_not_allowed\",\n `[Sixb] OIDC authorization attempt '${input.oidcAuthorizationAttemptId}' cannot create a user for project '${projectId}'.`\n )\n }\n\n if (\n shouldCreateUser &&\n !activeInvitation &&\n input.allowUserCreationWithoutInvitation &&\n input.requireNoActiveUsersForUserCreation &&\n hasActiveUsers(this.state, projectId)\n ) {\n this.consumeOidcAttempt(input, completedAt, projectId)\n throw new AuthStorageError(\n \"user_creation_not_allowed\",\n `[Sixb] OIDC authorization attempt '${input.oidcAuthorizationAttemptId}' cannot create a user for project '${projectId}'.`\n )\n }\n\n validateCompleteSessionInput(this.state, projectId, input.session)\n assertSignInSessionAudience(projectId, input.session.audience, attempt.audience)\n\n let newUserId: string | undefined\n if (shouldCreateUser) {\n newUserId = assertNonEmpty(input.newUserId, \"User id\")\n if (this.state.users.has(userKey(projectId, newUserId))) {\n throw new AuthStorageError(\n \"duplicate_user\",\n `[Sixb] User '${newUserId}' already exists for project '${projectId}'.`\n )\n }\n }\n\n this.consumeOidcAttempt(input, completedAt, projectId)\n\n if (!user) {\n user = {\n id: newUserId ?? assertNonEmpty(input.newUserId, \"User id\"),\n projectId,\n email,\n displayName: input.displayName,\n avatarUrl: input.avatarUrl,\n status: \"active\",\n createdAt: completedAt,\n updatedAt: completedAt,\n }\n this.state.users.set(userKey(projectId, user.id), cloneRecord(user))\n }\n\n const invitation = this.acceptInvitationAndApplyGroups({\n activeInvitation,\n completedAt,\n projectId,\n user,\n })\n const memberships = this.applyManualGroups({\n completedAt,\n groupIds: manualGroupIds,\n projectId,\n userId: user.id,\n existing: invitation.memberships,\n })\n\n const nextIdentity: UserIdentityRecord = {\n projectId,\n strategyId: attempt.strategyId,\n subject,\n userId: user.id,\n claims,\n createdAt: identity?.createdAt ?? completedAt,\n updatedAt: completedAt,\n }\n this.state.identities.set(\n identityKey(projectId, attempt.strategyId, subject),\n cloneRecord(nextIdentity)\n )\n\n const session = this.createSignInSession({\n projectId,\n strategyId: attempt.strategyId,\n session: input.session,\n userId: user.id,\n })\n\n return {\n user: cloneRecord(user),\n session: cloneRecord(session),\n identity: cloneRecord(nextIdentity),\n invitation: invitation.invitation ? cloneRecord(invitation.invitation) : undefined,\n groupMemberships: memberships.map(cloneRecord),\n }\n }\n\n async suspendUserAndRevokeSessions(\n input: SuspendUserAndRevokeSessionsInput\n ): Promise<UserRecord> {\n const key = userKey(input.projectId, input.userId)\n const existing = this.state.users.get(key)\n\n if (!existing) {\n throw new AuthStorageError(\n \"missing_user\",\n `[Sixb] User '${input.userId}' not found for project '${input.projectId}'.`\n )\n }\n\n const next: UserRecord = {\n ...existing,\n status: \"suspended\",\n updatedAt: cloneDate(input.suspendedAt),\n }\n this.state.users.set(key, cloneRecord(next))\n revokeActiveSessionsForUser(this.state, input.projectId, input.userId, input.suspendedAt)\n\n return cloneRecord(next)\n }\n\n private acceptInvitationAndApplyGroups(input: {\n readonly activeInvitation: InvitationRecord | null\n readonly completedAt: Date\n readonly projectId: string\n readonly user: UserRecord\n }): {\n readonly invitation?: InvitationRecord\n readonly memberships: readonly GroupMembershipRecord[]\n } {\n if (!input.activeInvitation) {\n return { memberships: [] }\n }\n\n const invitation: InvitationRecord = {\n ...input.activeInvitation,\n status: \"accepted\",\n acceptedAt: input.completedAt,\n updatedAt: input.completedAt,\n }\n this.state.invitations.set(\n invitationKey(input.projectId, invitation.id),\n cloneRecord(invitation)\n )\n\n const memberships = input.activeInvitation.groupIds.map((groupId) =>\n upsertGroupMembershipRecord(this.state, {\n projectId: input.projectId,\n userId: input.user.id,\n groupId,\n source: \"invitation\",\n createdAt: input.completedAt,\n })\n )\n\n return { invitation, memberships }\n }\n\n private applyManualGroups(input: {\n readonly completedAt: Date\n readonly groupIds: readonly string[]\n readonly projectId: string\n readonly userId: string\n readonly existing: readonly GroupMembershipRecord[]\n }): readonly GroupMembershipRecord[] {\n const memberships = [...input.existing]\n for (const groupId of input.groupIds) {\n memberships.push(\n upsertGroupMembershipRecord(this.state, {\n projectId: input.projectId,\n userId: input.userId,\n groupId,\n source: \"manual\",\n createdAt: input.completedAt,\n })\n )\n }\n return memberships\n }\n\n private createSignInSession(input: {\n readonly projectId: string\n readonly strategyId: string\n readonly session: CompleteMagicLinkSignInInput[\"session\"]\n readonly userId: string\n }): SessionRecord {\n return createSessionRecord(this.state, {\n id: input.session.id,\n projectId: input.projectId,\n userId: input.userId,\n strategyId: input.strategyId,\n audience: input.session.audience,\n tokenHash: input.session.tokenHash,\n createdAt: input.session.createdAt,\n expiresAt: input.session.expiresAt,\n absoluteExpiresAt: input.session.absoluteExpiresAt,\n userAgent: input.session.userAgent,\n ipAddress: input.session.ipAddress,\n })\n }\n\n private consumeOidcAttempt(\n input: CompleteOidcSignInInput,\n completedAt: Date,\n projectId: string\n ): void {\n consumeOidcAttemptRecord(this.state, {\n projectId,\n id: input.oidcAuthorizationAttemptId,\n stateHash: input.stateHash,\n consumedAt: completedAt,\n })\n }\n}\n\nexport type InMemoryAuthStorageSnapshot = AuthStorageState\n\nfunction restoreMap<TKey, TValue>(target: Map<TKey, TValue>, snapshot: Map<TKey, TValue>): void {\n target.clear()\n for (const [key, value] of structuredClone(snapshot)) {\n target.set(key, value)\n }\n}\n\nfunction hasActiveUsers(state: AuthStorageState, projectId: string): boolean {\n for (const user of state.users.values()) {\n if (user.projectId === projectId && user.status === \"active\") {\n return true\n }\n }\n\n return false\n}\n\nfunction assertSignInSessionAudience(\n projectId: string,\n sessionAudience: string,\n storedAudience: string\n): void {\n if (sessionAudience === storedAudience) {\n return\n }\n\n throw new AuthStorageError(\n \"invalid_input\",\n `[Sixb] Sign-in session audience '${sessionAudience}' does not match stored auth audience '${storedAudience}' for project '${projectId}'.`\n )\n}\n",
|
|
32
|
+
"import type { AuthSessionAudience } from \"./audience\"\nimport type { AuthenticatedAuthSession } from \"./types\"\n\ninterface SessionCacheEntry {\n readonly tokenHash: string\n readonly audience: AuthSessionAudience\n readonly session: AuthenticatedAuthSession\n readonly expiresAtMs: number\n}\n\nexport interface SessionCacheGetInput {\n readonly sessionId: string\n readonly tokenHash: string\n readonly audience: AuthSessionAudience\n readonly nowMs: number\n}\n\nexport interface SessionCacheSetInput extends SessionCacheGetInput {\n readonly session: AuthenticatedAuthSession\n readonly sessionExpiresAtMs: number\n readonly sessionAbsoluteExpiresAtMs?: number\n}\n\n/**\n * Tiny in-process TTL cache for resolved auth sessions, keyed by session id.\n *\n * Every authenticated request resolves its session through the shared storage pool\n * (a session lookup plus user and group-membership reads). Under request bursts that\n * triples the pool pressure and, with a small pool, can starve the pool so the entire\n * API stalls. Caching the resolved result for a short TTL collapses those reads to one\n * per session per window.\n *\n * Safety: entries are pinned to the exact token hash + audience that produced them and\n * are never served past the session's rolling or absolute deadline. The short TTL bounds how long\n * a revoked session can linger; sign-out additionally invalidates eagerly via\n * {@link SessionCache.invalidate}.\n */\nexport class SessionCache {\n private readonly entries = new Map<string, SessionCacheEntry>()\n\n constructor(\n private readonly ttlMs: number,\n private readonly maxEntries: number = 4096\n ) {}\n\n get(input: SessionCacheGetInput): AuthenticatedAuthSession | undefined {\n const entry = this.entries.get(input.sessionId)\n if (!entry) {\n return undefined\n }\n\n if (\n entry.expiresAtMs <= input.nowMs ||\n entry.tokenHash !== input.tokenHash ||\n entry.audience !== input.audience\n ) {\n this.entries.delete(input.sessionId)\n return undefined\n }\n\n return entry.session\n }\n\n set(input: SessionCacheSetInput): void {\n // Never let a cached session outlive the real session it represents.\n const expiresAtMs = Math.min(\n input.nowMs + this.ttlMs,\n input.sessionExpiresAtMs,\n input.sessionAbsoluteExpiresAtMs ?? Number.POSITIVE_INFINITY\n )\n if (expiresAtMs <= input.nowMs) {\n return\n }\n\n // Re-insert so the freshest key sorts last for insertion-order LRU eviction.\n this.entries.delete(input.sessionId)\n this.entries.set(input.sessionId, {\n tokenHash: input.tokenHash,\n audience: input.audience,\n session: input.session,\n expiresAtMs,\n })\n\n if (this.entries.size > this.maxEntries) {\n const oldest = this.entries.keys().next().value\n if (oldest !== undefined) {\n this.entries.delete(oldest)\n }\n }\n }\n\n invalidate(sessionId: string): void {\n this.entries.delete(sessionId)\n }\n\n /**\n * Drop every cached session for a user. Call this after a change that alters how\n * the user's session resolves (group reassignment, suspension) so the next request\n * re-reads storage instead of serving a stale principal.\n */\n invalidateUser(userId: string): void {\n for (const [sessionId, entry] of this.entries) {\n if (entry.session.user.id === userId) {\n this.entries.delete(sessionId)\n }\n }\n }\n\n clear(): void {\n this.entries.clear()\n }\n}\n",
|
|
33
|
+
"import { createHash, randomBytes, randomUUID } from \"node:crypto\"\n\nexport interface SessionCookieParts {\n readonly sessionId: string\n readonly sessionSecret: string\n}\n\nexport interface SessionCredential {\n readonly sessionId: string\n readonly sessionSecret: string\n readonly tokenHash: string\n readonly cookieValue: string\n}\n\nexport function generateSessionSecret(): string {\n return randomBytes(32).toString(\"base64url\")\n}\n\nexport function hashSessionSecret(secret: string): string {\n return createHash(\"sha256\").update(secret).digest(\"hex\")\n}\n\nexport function formatSessionCookieValue(sessionId: string, sessionSecret: string): string {\n if (!sessionId || !sessionSecret || sessionId.includes(\".\") || sessionSecret.includes(\".\")) {\n throw new Error(\"[Sixb] Session cookie values must be non-empty and must not contain '.'.\")\n }\n\n return `${sessionId}.${sessionSecret}`\n}\n\nexport function parseSessionCookieValue(value: string | undefined): SessionCookieParts | null {\n if (!value) {\n return null\n }\n\n const firstDot = value.indexOf(\".\")\n if (firstDot <= 0 || firstDot !== value.lastIndexOf(\".\") || firstDot === value.length - 1) {\n return null\n }\n\n return {\n sessionId: value.slice(0, firstDot),\n sessionSecret: value.slice(firstDot + 1),\n }\n}\n\nexport function createSessionCredential(sessionId = `ses_${randomUUID()}`): SessionCredential {\n const sessionSecret = generateSessionSecret()\n return {\n sessionId,\n sessionSecret,\n tokenHash: hashSessionSecret(sessionSecret),\n cookieValue: formatSessionCookieValue(sessionId, sessionSecret),\n }\n}\n",
|
|
34
|
+
"import type { GroupDefinition, GroupReference, MembershipOperation } from \"../security\"\nimport type {\n AccessTokenRecord,\n AuthStorage,\n CompleteAuthSessionInput,\n CompleteSignInResult,\n InvitationRecord,\n InvitationStatus,\n ServiceAccountGroupMembershipRecord,\n ServiceAccountRecord,\n SessionRecord,\n UserRecord,\n} from \"../storage/auth\"\nimport type { AuthSessionAudience, AuthSessionAudienceOptions } from \"./audience\"\n\nexport type Principal =\n | { readonly type: \"user\"; readonly id: string }\n | { readonly type: \"serviceAccount\"; readonly id: string }\n | { readonly type: \"system\"; readonly id: string }\n\n/**\n * The canonical principal for system-originated writes (runs triggered without a caller,\n * worker fallbacks, decode-time defaults). Import this everywhere instead of inlining a\n * `{ type: \"system\", id: \"system\" }` literal so the system identity never forks.\n */\nexport const SYSTEM_PRINCIPAL: Principal = { type: \"system\", id: \"system\" }\n\n/** Structural equality for principals (same type and id). */\nexport function principalsEqual(left: Principal, right: Principal): boolean {\n return left.type === right.type && left.id === right.id\n}\n\nexport interface SecurityContext {\n readonly principal: Principal\n readonly sessionId?: string\n readonly projectId: string\n readonly correlationId: string\n}\n\nexport type AuthStrategyKind = \"magicLink\" | \"oidc\" | \"dev\" | \"disabled\"\n\nexport interface AuthStrategy {\n readonly id: string\n readonly kind: AuthStrategyKind\n readonly developmentOnly?: boolean\n readonly disabled?: boolean\n readonly allowDisabledInProduction?: boolean\n}\n\nexport interface InvitationRecipientInput {\n readonly projectId: string\n readonly authStorage: AuthStorage\n readonly email: string\n readonly now?: Date\n}\n\nexport type InvitationRecipientStatus =\n | \"allowed\"\n | \"invalid_email\"\n | \"disallowed_domain\"\n | \"suspended_user\"\n | \"rate_limited\"\n\nexport interface InvitationRecipientResult {\n readonly status: InvitationRecipientStatus\n readonly email?: string\n}\n\nexport interface InvitationDeliveryInput {\n readonly projectId: string\n readonly authStorage: AuthStorage\n readonly invitation: InvitationRecord\n readonly audience: AuthSessionAudience\n readonly returnTo: string\n readonly requestOrigin: string\n /** Return the delivered link once so the inviter can copy it through an approved channel. */\n readonly revealLink?: boolean\n readonly now?: Date\n}\n\nexport type AuthEmailDeliveryStatus = \"sent\" | \"skipped\" | \"rate_limited\"\n\nexport type InviteDeliveryStatus = AuthEmailDeliveryStatus | \"not_supported\"\n\nexport interface RevealedInvitationLink {\n readonly url: string\n readonly expiresAt?: Date\n}\n\nexport interface InviteDeliveryResult {\n readonly status: InviteDeliveryStatus\n /**\n * Present only when the caller explicitly requests `revealLink`. Treat this as a credential:\n * never persist it or include it in list responses, logs, or analytics.\n */\n readonly link?: RevealedInvitationLink\n}\n\nexport interface InvitationDeliveryAuthStrategy extends AuthStrategy {\n validateInvitationRecipient?(input: InvitationRecipientInput): Promise<InvitationRecipientResult>\n deliverInvitation(input: InvitationDeliveryInput): Promise<InviteDeliveryResult>\n}\n\nexport interface MagicLinkRequestInput {\n readonly projectId: string\n readonly authStorage: AuthStorage\n readonly email: string\n readonly audience: AuthSessionAudience\n readonly returnTo: string\n readonly requestOrigin: string\n /**\n * Opaque hash the strategy appends to the callback URL as the `requester`\n * query param. The server keeps the preimage in a cookie on the requesting\n * browser so the callback can sign that same browser in without the extra\n * confirmation click. Omitted for deliveries with no requesting browser\n * (invitations).\n */\n readonly requesterHash?: string\n readonly now?: Date\n}\n\nexport type MagicLinkRequestStatus = AuthEmailDeliveryStatus\n\nexport interface MagicLinkRequestResult {\n readonly status: MagicLinkRequestStatus\n}\n\nexport type AuthInvitationRecipientInput = InvitationRecipientInput\n\nexport type AuthInvitationRecipientStatus = InvitationRecipientStatus\n\nexport type AuthInvitationRecipientResult = InvitationRecipientResult\n\nexport type MagicLinkInvitationRecipientInput = InvitationRecipientInput\n\nexport type MagicLinkInvitationRecipientStatus = InvitationRecipientStatus\n\nexport type MagicLinkInvitationRecipientResult = InvitationRecipientResult\n\nexport interface MagicLinkCallbackInput {\n readonly projectId: string\n readonly authStorage: AuthStorage\n readonly magicLinkId: string\n readonly token: string\n readonly session: CompleteAuthSessionInput\n readonly now?: Date\n}\n\nexport interface MagicLinkCallbackResult extends CompleteSignInResult {\n readonly audience: AuthSessionAudience\n readonly returnTo: string\n}\n\nexport interface MagicLinkPeekInput {\n readonly projectId: string\n readonly authStorage: AuthStorage\n readonly magicLinkId: string\n readonly token: string\n readonly now?: Date\n}\n\nexport interface MagicLinkPeekResult {\n readonly email: string\n}\n\nexport interface MagicLinkAuthStrategy extends InvitationDeliveryAuthStrategy {\n readonly kind: \"magicLink\"\n readonly bootstrapGroupIds?: readonly string[]\n /**\n * How long issued links stay valid (ms). Lets the server align dependent\n * lifetimes (e.g. the same-device pending cookie) with the configured TTL.\n */\n readonly magicLinkTtlMs?: number\n validateInvitationRecipient?(\n input: MagicLinkInvitationRecipientInput\n ): Promise<MagicLinkInvitationRecipientResult>\n requestMagicLink(input: MagicLinkRequestInput): Promise<MagicLinkRequestResult>\n /**\n * Read-only validity check for a link the user has not confirmed yet. Must\n * never consume the token, and must apply the same rules that would make\n * {@link completeMagicLinkSignIn} fail (including token verification), so a\n * link that peeks as valid only fails to complete when raced. Returns null\n * for links that cannot complete sign-in.\n */\n peekMagicLink?(input: MagicLinkPeekInput): Promise<MagicLinkPeekResult | null>\n completeMagicLinkSignIn(input: MagicLinkCallbackInput): Promise<MagicLinkCallbackResult>\n}\n\nexport interface OidcStartSignInInput {\n readonly projectId: string\n readonly authStorage: AuthStorage\n readonly audience: AuthSessionAudience\n readonly returnTo: string\n readonly requestOrigin: string\n readonly now?: Date\n}\n\nexport interface OidcStartSignInResult {\n readonly redirectTo: string\n}\n\nexport interface OidcCallbackInput {\n readonly projectId: string\n readonly authStorage: AuthStorage\n readonly requestUrl: string\n readonly requestOrigin: string\n readonly session: CompleteAuthSessionInput\n readonly now?: Date\n}\n\nexport interface OidcCallbackResult extends CompleteSignInResult {\n readonly audience: AuthSessionAudience\n readonly returnTo: string\n}\n\nexport interface OidcAuthStrategy extends InvitationDeliveryAuthStrategy {\n readonly kind: \"oidc\"\n readonly bootstrapGroupIds?: readonly string[]\n startOidcSignIn(input: OidcStartSignInInput): Promise<OidcStartSignInResult>\n completeOidcSignIn(input: OidcCallbackInput): Promise<OidcCallbackResult>\n}\n\nexport interface InviteUserInput {\n readonly email: string\n readonly groups?: readonly GroupDefinition[]\n readonly groupIds?: readonly string[]\n readonly expiresAt?: Date\n readonly returnTo?: string\n /** Reveal the delivered link once in the result. Defaults to false. */\n readonly revealLink?: boolean\n}\n\nexport interface InviteUserResult {\n readonly invitation: InvitationRecord\n readonly delivery: InviteDeliveryResult\n}\n\nexport interface ListInvitationsInput {\n readonly email?: string\n readonly statuses?: readonly InvitationStatus[]\n readonly limit?: number\n readonly offset?: number\n readonly order?: \"asc\" | \"desc\"\n}\n\nexport interface ListInvitationsResult {\n readonly invitations: readonly InvitationRecord[]\n readonly hasMore: boolean\n readonly total: number\n}\n\nexport interface InvitationGroupOption {\n readonly id: string\n readonly label?: string\n readonly description?: string\n}\n\nexport type CreateInvitationCapability =\n | { readonly state: \"enabled\" }\n | {\n readonly state: \"disabled\"\n readonly reason: \"missing_membership_policy\" | \"invitation_delivery_not_supported\"\n }\n\nexport interface GetInvitationOptionsResult {\n readonly groups: readonly InvitationGroupOption[]\n readonly canInviteWithoutGroups: boolean\n readonly capabilities: {\n readonly createInvitation: CreateInvitationCapability\n }\n}\n\n/**\n * Which membership operations the caller holds at least one policy for. Coarse,\n * caller-wide capabilities used to gate top-level UI affordances; per-target\n * checks (scope over a member's current groups, self-protection) are finer.\n */\nexport interface MembershipOperationCapabilities {\n readonly invite: boolean\n readonly assignGroups: boolean\n readonly suspend: boolean\n}\n\nexport interface GetMembershipOptionsResult {\n /** Groups the caller may assign to a member (the `assignGroups` scope). */\n readonly groups: readonly InvitationGroupOption[]\n readonly capabilities: MembershipOperationCapabilities\n}\n\n/**\n * What a caller's membership policies let it do — the answer to \"may this principal invite?\".\n *\n * Resolved from group ids alone, with no HTTP request involved, so project code and tests can ask the\n * question the same way the member-admin routes do.\n */\nexport interface MembershipCapabilities {\n /** True when at least one policy grants the operation, ignoring which groups it covers. */\n readonly holds: MembershipOperationCapabilities\n /** Group ids the caller may assign to a member. */\n readonly assignableGroupIds: readonly string[]\n /**\n * Whether the caller's policy scope reaches a member currently holding exactly `memberGroups`.\n *\n * Pass definitions when your code knows the groups (`covers(\"suspend\", [teamMembers])`) and ids when\n * they came from a session or a member's stored memberships. An empty list asks the group-less case —\n * inviting someone who joins no group — which any holder of the operation may do.\n *\n * Coverage is not authorization. It is the group boundary the membership policies draw, which is what\n * a UI needs to decide whether to offer a control for a given member. The operation itself applies\n * rules this question cannot see: `suspendMember` refuses the current user, `assignGroups` also checks\n * the groups being assigned against `assignableGroupIds`, and a member's status can rule it out. Ask\n * the runtime method for the decision; ask this for the boundary.\n */\n covers(operation: MembershipOperation, memberGroups: readonly GroupReference[]): boolean\n}\n\nexport interface ListMembersInput {\n readonly limit?: number\n readonly offset?: number\n readonly order?: \"asc\" | \"desc\"\n}\n\n/** Per-target actions the caller may take on a member, after self-protection. */\nexport interface MemberCapabilities {\n readonly assignGroups: boolean\n readonly suspend: boolean\n readonly reactivate: boolean\n}\n\nexport interface MemberSummary {\n readonly user: UserRecord\n readonly groupIds: readonly string[]\n readonly capabilities: MemberCapabilities\n}\n\nexport interface ListMembersResult {\n readonly members: readonly MemberSummary[]\n readonly hasMore: boolean\n readonly total: number\n}\n\nexport interface UpdateMemberGroupsInput {\n readonly userId: string\n /** The desired full set of groups; additions and removals are derived from it. */\n readonly groupIds: readonly string[]\n}\n\nexport interface UpdateMemberGroupsResult {\n readonly user: UserRecord\n readonly groupIds: readonly string[]\n}\n\nexport interface SuspendMemberInput {\n readonly userId: string\n}\n\nexport interface SuspendMemberResult {\n readonly user: UserRecord\n readonly groupIds: readonly string[]\n}\n\nexport interface ReactivateMemberInput {\n readonly userId: string\n}\n\nexport interface ReactivateMemberResult {\n readonly user: UserRecord\n readonly groupIds: readonly string[]\n}\n\nexport type AuthCredentialSource = \"session\" | \"accessToken\" | \"any\"\n\nexport interface AuthSessionResolutionOptions extends AuthSessionAudienceOptions {\n readonly credentialSource?: AuthCredentialSource\n /** Marks this request as eligible to renew a near-expiry browser session. */\n readonly sessionActivity?: \"foreground\"\n}\n\nexport interface InviteUserOptions extends AuthSessionAudienceOptions {\n readonly delivery?: {\n readonly audience?: AuthSessionAudience\n readonly requestOrigin?: string\n readonly returnTo?: string\n }\n}\n\nexport interface RevokeInvitationInput {\n readonly invitationId: string\n}\n\nexport interface RevokeInvitationResult {\n readonly invitation: InvitationRecord\n}\n\nexport interface CreatePersonalAccessTokenInput {\n readonly name: string\n readonly expiresAt: Date\n readonly groupIds?: readonly string[]\n}\n\nexport interface CreateServiceAccountInput {\n readonly id?: string\n readonly name: string\n readonly description?: string\n readonly groupIds?: readonly string[]\n}\n\nexport interface CreateServiceAccountResult {\n readonly serviceAccount: ServiceAccountRecord\n readonly groupMemberships: readonly ServiceAccountGroupMembershipRecord[]\n}\n\nexport interface CreateServiceAccountAccessTokenInput {\n readonly serviceAccountId: string\n readonly name: string\n readonly expiresAt: Date\n readonly groupIds?: readonly string[]\n}\n\nexport interface CreateAccessTokenResult {\n readonly accessToken: AccessTokenRecord\n readonly tokenValue: string\n}\n\nexport interface CreateServiceAccountAccessTokenResult extends CreateAccessTokenResult {\n readonly serviceAccount: ServiceAccountRecord\n}\n\nexport interface ServiceAccountWithGroups {\n readonly serviceAccount: ServiceAccountRecord\n readonly groupIds: readonly string[]\n}\n\nexport interface ListServiceAccountsResult {\n readonly serviceAccounts: readonly ServiceAccountWithGroups[]\n}\n\nexport interface ListPersonalAccessTokensResult {\n readonly accessTokens: readonly AccessTokenRecord[]\n}\n\nexport interface ListServiceAccountAccessTokensInput {\n readonly serviceAccountId: string\n}\n\nexport interface ListServiceAccountAccessTokensResult {\n readonly serviceAccount: ServiceAccountRecord\n readonly accessTokens: readonly AccessTokenRecord[]\n}\n\nexport interface DisableServiceAccountInput {\n readonly serviceAccountId: string\n}\n\nexport interface DisableServiceAccountResult {\n readonly serviceAccount: ServiceAccountRecord\n readonly groupIds: readonly string[]\n}\n\nexport interface RevokePersonalAccessTokenInput {\n readonly tokenId: string\n}\n\nexport interface RevokeServiceAccountAccessTokenInput {\n readonly serviceAccountId: string\n readonly tokenId: string\n}\n\nexport interface RevokeAccessTokenResult {\n readonly accessToken: AccessTokenRecord\n}\n\nexport interface RevokeServiceAccountAccessTokenResult {\n readonly serviceAccount: ServiceAccountRecord\n readonly accessToken: AccessTokenRecord\n}\n\nexport interface AuthSessionOptions {\n /** How long a browser session may remain idle before it expires. Defaults to 30 days. */\n readonly idleTimeoutMs?: number\n /** How close to idle expiry a foreground request must be before renewal. Defaults to 7 days. */\n readonly renewalWindowMs?: number\n /**\n * Optional maximum lifetime that foreground activity cannot extend. Captured when the session\n * is created, so later configuration changes affect only newly issued sessions. Disabled by\n * default.\n */\n readonly absoluteTimeoutMs?: number\n /**\n * How long (ms) a resolved session is cached in-process before it is re-validated\n * against storage. Collapses the per-request auth reads (session + user + memberships)\n * during request bursts so they cannot starve the storage pool. Set to 0 to disable.\n * Defaults to {@link DEFAULT_AUTH_SESSION_CACHE_TTL_MS}.\n */\n readonly cacheTtlMs?: number\n}\n\nexport interface ResolvedAuthSessionOptions {\n readonly idleTimeoutMs: number\n readonly renewalWindowMs: number\n readonly absoluteTimeoutMs?: number\n readonly cacheTtlMs: number\n}\n\nexport interface AuthCookieOptions {\n readonly sessionCookieName?: string\n readonly csrfCookieName?: string\n readonly cookieDomain?: string\n readonly secure?: boolean | \"auto\"\n readonly sameSite?: \"strict\"\n readonly csrfHttpOnly?: boolean\n}\n\nexport type SixbAuthConfig =\n | AuthStrategy\n | {\n readonly strategy: AuthStrategy\n readonly session?: AuthSessionOptions\n readonly cookies?: AuthCookieOptions\n }\n\nexport type AuthSessionFailureReason =\n | \"auth_disabled\"\n | \"missing_credentials\"\n | \"missing_cookie\"\n | \"missing_access_token\"\n | \"invalid_cookie\"\n | \"invalid_access_token\"\n | \"invalid_session\"\n | \"missing_user\"\n | \"missing_service_account\"\n | \"suspended_service_account\"\n | \"suspended_user\"\n\nexport interface UnauthenticatedAuthSession {\n readonly authenticated: false\n readonly reason: AuthSessionFailureReason\n}\n\nexport interface AuthenticatedAuthSession {\n readonly authenticated: true\n readonly credentialSource: \"session\"\n readonly principal: Extract<Principal, { readonly type: \"user\" }>\n readonly user: UserRecord\n readonly session: SessionRecord\n readonly groupIds: readonly string[]\n /** Internal response hint: the rolling session deadline advanced during this request. */\n readonly sessionRenewed?: true\n}\n\nexport interface AuthenticatedUserAccessTokenSession {\n readonly authenticated: true\n readonly credentialSource: \"accessToken\"\n readonly principal: Extract<Principal, { readonly type: \"user\" }>\n readonly user: UserRecord\n readonly accessToken: AccessTokenRecord\n readonly groupIds: readonly string[]\n}\n\nexport interface AuthenticatedServiceAccountAccessTokenSession {\n readonly authenticated: true\n readonly credentialSource: \"accessToken\"\n readonly principal: Extract<Principal, { readonly type: \"serviceAccount\" }>\n readonly serviceAccount: ServiceAccountRecord\n readonly accessToken: AccessTokenRecord\n readonly groupIds: readonly string[]\n}\n\nexport type AuthSessionResult = UnauthenticatedAuthSession | AuthenticatedAuthSession\n\nexport type AuthenticatedUserRequestSession =\n | AuthenticatedAuthSession\n | AuthenticatedUserAccessTokenSession\n\nexport type AuthenticatedRequestAuthSession =\n | AuthenticatedUserRequestSession\n | AuthenticatedServiceAccountAccessTokenSession\n\nexport type AuthRequestResult = UnauthenticatedAuthSession | AuthenticatedRequestAuthSession\n\nexport interface ResolvedAuthConfig {\n readonly strategy: AuthStrategy | null\n readonly session: ResolvedAuthSessionOptions\n readonly cookies: Required<Omit<AuthCookieOptions, \"cookieDomain\">> & {\n readonly domain?: string\n }\n}\n"
|
|
35
|
+
],
|
|
36
|
+
"mappings": "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",
|
|
37
|
+
"debugId": "D187F2B23E70181D64756E2164756E21",
|
|
38
|
+
"names": []
|
|
39
|
+
}
|