@sixb/core 0.1.21 → 0.1.22
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/commit-edits.d.ts +3 -1
- package/dist/actions/commit-edits.d.ts.map +1 -1
- package/dist/actions/execution.d.ts.map +1 -1
- package/dist/actions/index.js +63 -59
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/read-facade.d.ts +9 -1
- package/dist/actions/read-facade.d.ts.map +1 -1
- package/dist/actions/request.d.ts +15 -1
- package/dist/actions/request.d.ts.map +1 -1
- package/dist/actions/run/context.d.ts +1 -0
- package/dist/actions/run/context.d.ts.map +1 -1
- package/dist/actions/run/execute.d.ts +2 -3
- package/dist/actions/run/execute.d.ts.map +1 -1
- package/dist/actions/run/executor.d.ts +3 -0
- package/dist/actions/run/executor.d.ts.map +1 -1
- package/dist/actions/run/normalize.d.ts +2 -1
- package/dist/actions/run/normalize.d.ts.map +1 -1
- package/dist/actions/run/signals.d.ts +1 -3
- package/dist/actions/run/signals.d.ts.map +1 -1
- package/dist/actions/run/types.d.ts +16 -1
- package/dist/actions/run/types.d.ts.map +1 -1
- package/dist/actions/run-authorization.d.ts +14 -0
- package/dist/actions/run-authorization.d.ts.map +1 -1
- package/dist/actions/types/context.d.ts +17 -1
- package/dist/actions/types/context.d.ts.map +1 -1
- package/dist/actions/validators.d.ts.map +1 -1
- package/dist/activity/timeline.d.ts +8 -1
- package/dist/activity/timeline.d.ts.map +1 -1
- package/dist/agents/accounting.d.ts +15 -0
- package/dist/agents/accounting.d.ts.map +1 -0
- package/dist/agents/adapters.d.ts.map +1 -1
- package/dist/agents/agent-mail.d.ts +9 -0
- package/dist/agents/agent-mail.d.ts.map +1 -0
- package/dist/agents/api-gateway.d.ts +5 -0
- package/dist/agents/api-gateway.d.ts.map +1 -1
- package/dist/agents/approval-continuation.d.ts +23 -0
- package/dist/agents/approval-continuation.d.ts.map +1 -0
- package/dist/agents/approval-executor.d.ts +56 -0
- package/dist/agents/approval-executor.d.ts.map +1 -0
- package/dist/agents/approval-outcome.d.ts +8 -0
- package/dist/agents/approval-outcome.d.ts.map +1 -0
- package/dist/agents/approvals.d.ts +210 -0
- package/dist/agents/approvals.d.ts.map +1 -0
- package/dist/agents/authority.d.ts +10 -0
- package/dist/agents/authority.d.ts.map +1 -1
- package/dist/agents/builders.d.ts.map +1 -1
- package/dist/agents/cancel.d.ts +23 -0
- package/dist/agents/cancel.d.ts.map +1 -0
- package/dist/agents/child-question.d.ts +18 -0
- package/dist/agents/child-question.d.ts.map +1 -0
- package/dist/agents/children.d.ts +99 -0
- package/dist/agents/children.d.ts.map +1 -0
- package/dist/agents/context/index.js +1 -1
- package/dist/agents/context-compaction.d.ts.map +1 -1
- package/dist/agents/errors.d.ts +13 -1
- package/dist/agents/errors.d.ts.map +1 -1
- package/dist/agents/execution.d.ts +180 -14
- package/dist/agents/execution.d.ts.map +1 -1
- package/dist/agents/fork.d.ts +16 -0
- package/dist/agents/fork.d.ts.map +1 -0
- package/dist/agents/ids.d.ts +7 -0
- package/dist/agents/ids.d.ts.map +1 -1
- package/dist/agents/index.d.ts +19 -8
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +159 -86
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/memory-execution.d.ts +57 -0
- package/dist/agents/memory-execution.d.ts.map +1 -0
- package/dist/agents/memory.d.ts +49 -0
- package/dist/agents/memory.d.ts.map +1 -0
- package/dist/agents/message.d.ts +50 -1
- package/dist/agents/message.d.ts.map +1 -1
- package/dist/agents/model-loop.d.ts +19 -0
- package/dist/agents/model-loop.d.ts.map +1 -1
- package/dist/agents/model-routing.d.ts +19 -0
- package/dist/agents/model-routing.d.ts.map +1 -0
- package/dist/agents/participants.d.ts +18 -0
- package/dist/agents/participants.d.ts.map +1 -0
- package/dist/agents/reference.d.ts.map +1 -1
- package/dist/agents/request.d.ts +36 -2
- package/dist/agents/request.d.ts.map +1 -1
- package/dist/agents/run-scope.d.ts +51 -0
- package/dist/agents/run-scope.d.ts.map +1 -0
- package/dist/agents/streams/index.d.ts +3 -2
- package/dist/agents/streams/index.d.ts.map +1 -1
- package/dist/agents/streams/index.js +7 -3
- package/dist/agents/streams/index.js.map +1 -1
- package/dist/agents/streams/internal.d.ts +1 -1
- package/dist/agents/streams/internal.d.ts.map +1 -1
- package/dist/agents/streams/internal.js +5 -3
- package/dist/agents/streams/internal.js.map +1 -1
- package/dist/agents/streams/protocol.d.ts +122 -3
- package/dist/agents/streams/protocol.d.ts.map +1 -1
- package/dist/agents/subagent-runs.d.ts +12 -0
- package/dist/agents/subagent-runs.d.ts.map +1 -0
- package/dist/agents/thread-access.d.ts +53 -0
- package/dist/agents/thread-access.d.ts.map +1 -0
- package/dist/agents/tool-definition.d.ts +5 -4
- package/dist/agents/tool-definition.d.ts.map +1 -1
- package/dist/agents/types.d.ts +23 -4
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/agents/validation.d.ts +1 -1
- package/dist/agents/validation.d.ts.map +1 -1
- package/dist/artifacts/access.d.ts +52 -0
- package/dist/artifacts/access.d.ts.map +1 -0
- package/dist/artifacts/canvas.d.ts +92 -0
- package/dist/artifacts/canvas.d.ts.map +1 -0
- package/dist/artifacts/csv.d.ts +5 -0
- package/dist/artifacts/csv.d.ts.map +1 -1
- package/dist/artifacts/errors.d.ts +7 -2
- package/dist/artifacts/errors.d.ts.map +1 -1
- package/dist/artifacts/execution.d.ts +102 -7
- package/dist/artifacts/execution.d.ts.map +1 -1
- package/dist/artifacts/formula/check.d.ts +24 -0
- package/dist/artifacts/formula/check.d.ts.map +1 -0
- package/dist/artifacts/formula/evaluate.d.ts +32 -0
- package/dist/artifacts/formula/evaluate.d.ts.map +1 -0
- package/dist/artifacts/formula/index.d.ts +38 -0
- package/dist/artifacts/formula/index.d.ts.map +1 -0
- package/dist/artifacts/formula/parser.d.ts +67 -0
- package/dist/artifacts/formula/parser.d.ts.map +1 -0
- package/dist/artifacts/frames/assets.d.ts +11 -9
- package/dist/artifacts/frames/assets.d.ts.map +1 -1
- package/dist/artifacts/frames/entries.d.ts +19 -0
- package/dist/artifacts/frames/entries.d.ts.map +1 -0
- package/dist/artifacts/frames/grants.d.ts +6 -6
- package/dist/artifacts/frames/grants.d.ts.map +1 -1
- package/dist/artifacts/frames/index.d.ts +4 -2
- package/dist/artifacts/frames/index.d.ts.map +1 -1
- package/dist/artifacts/frames/index.js +444 -51
- package/dist/artifacts/frames/index.js.map +10 -8
- package/dist/artifacts/frames/kit.d.ts +10 -5
- package/dist/artifacts/frames/kit.d.ts.map +1 -1
- package/dist/artifacts/frames/probe.d.ts +16 -12
- package/dist/artifacts/frames/probe.d.ts.map +1 -1
- package/dist/artifacts/frames/protocol.d.ts +79 -10
- package/dist/artifacts/frames/protocol.d.ts.map +1 -1
- package/dist/artifacts/frames/runtime.d.ts +27 -9
- package/dist/artifacts/frames/runtime.d.ts.map +1 -1
- package/dist/artifacts/index.d.ts +11 -5
- package/dist/artifacts/index.d.ts.map +1 -1
- package/dist/artifacts/index.js +128 -6
- package/dist/artifacts/index.js.map +3 -3
- package/dist/artifacts/kinds.d.ts +1 -1
- package/dist/artifacts/kinds.d.ts.map +1 -1
- package/dist/artifacts/limits.d.ts +30 -0
- package/dist/artifacts/limits.d.ts.map +1 -1
- package/dist/artifacts/live-sheet.d.ts +65 -0
- package/dist/artifacts/live-sheet.d.ts.map +1 -0
- package/dist/artifacts/outline.d.ts +27 -1
- package/dist/artifacts/outline.d.ts.map +1 -1
- package/dist/artifacts/publish/index.d.ts +2 -0
- package/dist/artifacts/publish/index.d.ts.map +1 -1
- package/dist/artifacts/publish/index.js +59 -19
- package/dist/artifacts/publish/index.js.map +1 -1
- package/dist/artifacts/publish/publish.d.ts +43 -11
- package/dist/artifacts/publish/publish.d.ts.map +1 -1
- package/dist/artifacts/publish/queries.d.ts +33 -0
- package/dist/artifacts/publish/queries.d.ts.map +1 -0
- package/dist/artifacts/publish/references.d.ts +6 -3
- package/dist/artifacts/publish/references.d.ts.map +1 -1
- package/dist/artifacts/publish/validate/canvas.d.ts +18 -0
- package/dist/artifacts/publish/validate/canvas.d.ts.map +1 -0
- package/dist/artifacts/publish/validate/html.d.ts +20 -0
- package/dist/artifacts/publish/validate/html.d.ts.map +1 -0
- package/dist/artifacts/publish/validate/page.d.ts +15 -0
- package/dist/artifacts/publish/validate/page.d.ts.map +1 -0
- package/dist/artifacts/publish/validate/sheet.d.ts +11 -3
- package/dist/artifacts/publish/validate/sheet.d.ts.map +1 -1
- package/dist/artifacts/publish/validate/slides.d.ts +1 -7
- package/dist/artifacts/publish/validate/slides.d.ts.map +1 -1
- package/dist/artifacts/queries.d.ts +95 -0
- package/dist/artifacts/queries.d.ts.map +1 -0
- package/dist/artifacts/resolve.d.ts +6 -0
- package/dist/artifacts/resolve.d.ts.map +1 -1
- package/dist/artifacts/run-query.d.ts +26 -0
- package/dist/artifacts/run-query.d.ts.map +1 -0
- package/dist/artifacts/serialize-query.d.ts +12 -0
- package/dist/artifacts/serialize-query.d.ts.map +1 -0
- package/dist/artifacts/sheet-rules.d.ts +26 -0
- package/dist/artifacts/sheet-rules.d.ts.map +1 -0
- package/dist/artifacts/tones.d.ts +8 -0
- package/dist/artifacts/tones.d.ts.map +1 -0
- package/dist/artifacts/workbook.d.ts +76 -5
- package/dist/artifacts/workbook.d.ts.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +14 -11
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/member-events.d.ts +13 -0
- package/dist/auth/member-events.d.ts.map +1 -0
- package/dist/auth/profile.d.ts +11 -0
- package/dist/auth/profile.d.ts.map +1 -0
- package/dist/auth/runtime.d.ts +31 -3
- package/dist/auth/runtime.d.ts.map +1 -1
- package/dist/auth/strategy.d.ts +3 -1
- package/dist/auth/strategy.d.ts.map +1 -1
- package/dist/auth/strategy.js +7 -3
- package/dist/auth/strategy.js.map +1 -1
- package/dist/auth/types.d.ts +30 -1
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/authorization/decision.d.ts +15 -0
- package/dist/authorization/decision.d.ts.map +1 -1
- package/dist/authorization/event-visibility.d.ts +5 -1
- package/dist/authorization/event-visibility.d.ts.map +1 -1
- package/dist/authorization/grant-kinds.d.ts +2 -2
- package/dist/authorization/grant-kinds.d.ts.map +1 -1
- package/dist/authorization/index.d.ts +2 -2
- package/dist/authorization/index.d.ts.map +1 -1
- package/dist/authorization/index.js +12 -7
- package/dist/authorization/index.js.map +1 -1
- package/dist/authorization/resolve.d.ts +19 -1
- package/dist/authorization/resolve.d.ts.map +1 -1
- package/dist/authorization/run-visibility.d.ts +8 -1
- package/dist/authorization/run-visibility.d.ts.map +1 -1
- package/dist/authorization/types.d.ts +14 -0
- package/dist/authorization/types.d.ts.map +1 -1
- package/dist/bootstrap/index.js +69 -65
- package/dist/bootstrap/index.js.map +2 -2
- package/dist/{chunk-ky3j490c.js → chunk-02bzjgnt.js} +6 -6
- package/dist/{chunk-ky3j490c.js.map → chunk-02bzjgnt.js.map} +1 -1
- package/dist/{chunk-mfs23znk.js → chunk-07kkp2e1.js} +1 -1
- package/dist/{chunk-c1rxbz5y.js → chunk-098anw4f.js} +21 -19
- package/dist/chunk-098anw4f.js.map +12 -0
- package/dist/{chunk-z58tm0hm.js → chunk-0phpbbvm.js} +3 -3
- package/dist/{chunk-ere85b8y.js → chunk-0xmt5p5y.js} +116 -27
- package/dist/chunk-0xmt5p5y.js.map +14 -0
- package/dist/{chunk-t6f3tdnr.js → chunk-16a9dmfy.js} +33 -2
- package/dist/{chunk-t6f3tdnr.js.map → chunk-16a9dmfy.js.map} +5 -4
- package/dist/chunk-18sk89cg.js +47 -0
- package/dist/chunk-18sk89cg.js.map +10 -0
- package/dist/{chunk-e17zdm62.js → chunk-1t6k1avb.js} +1 -1
- package/dist/chunk-2626mh4m.js +693 -0
- package/dist/chunk-2626mh4m.js.map +19 -0
- package/dist/{chunk-qczk96d9.js → chunk-2adz0h75.js} +13 -4
- package/dist/chunk-2adz0h75.js.map +11 -0
- package/dist/{chunk-kge7k6ey.js → chunk-2fn60nvs.js} +2 -2
- package/dist/{chunk-99nd4rc1.js → chunk-2gjj5dx3.js} +5 -4
- package/dist/{chunk-99nd4rc1.js.map → chunk-2gjj5dx3.js.map} +3 -3
- package/dist/{chunk-mjddfa7k.js → chunk-3fqxbn31.js} +2 -24
- package/dist/{chunk-mjddfa7k.js.map → chunk-3fqxbn31.js.map} +3 -4
- package/dist/{chunk-y0c4e6ex.js → chunk-3gbefjg5.js} +1 -1
- package/dist/{chunk-5hx48dnn.js → chunk-45ngkxkp.js} +52 -31
- package/dist/chunk-45ngkxkp.js.map +13 -0
- package/dist/{chunk-cy4mbddw.js → chunk-48jezz3j.js} +1 -1
- package/dist/{chunk-561r0yc9.js → chunk-4b26qwbg.js} +13 -13
- package/dist/{chunk-561r0yc9.js.map → chunk-4b26qwbg.js.map} +1 -1
- package/dist/{chunk-9k93ah50.js → chunk-4f3ydv7t.js} +33 -69
- package/dist/chunk-4f3ydv7t.js.map +10 -0
- package/dist/chunk-4y26vs3v.js +97 -0
- package/dist/chunk-4y26vs3v.js.map +10 -0
- package/dist/{chunk-4as3wt1c.js → chunk-4ymrcdbm.js} +7 -3
- package/dist/chunk-4ymrcdbm.js.map +12 -0
- package/dist/{chunk-hcbyfxbe.js → chunk-5grk14e5.js} +76 -2
- package/dist/{chunk-hcbyfxbe.js.map → chunk-5grk14e5.js.map} +4 -3
- package/dist/{chunk-8frc8a4j.js → chunk-65pyhyas.js} +90 -83
- package/dist/chunk-65pyhyas.js.map +20 -0
- package/dist/{chunk-hwksyjks.js → chunk-661ezhks.js} +182 -6
- package/dist/chunk-661ezhks.js.map +11 -0
- package/dist/{chunk-447a5c0p.js → chunk-6n69k945.js} +2 -2
- package/dist/{chunk-0bphap9y.js → chunk-6p0pastb.js} +5 -5
- package/dist/{chunk-9j4jw7as.js → chunk-6rrtzea3.js} +18 -5
- package/dist/chunk-6rrtzea3.js.map +14 -0
- package/dist/{chunk-431pyp2c.js → chunk-6y0mkhex.js} +2 -2
- package/dist/{chunk-f4pamkt9.js → chunk-73v685wb.js} +10 -10
- package/dist/{chunk-f4pamkt9.js.map → chunk-73v685wb.js.map} +3 -3
- package/dist/{chunk-akzryx9h.js → chunk-7gr4j2eq.js} +7836 -5047
- package/dist/chunk-7gr4j2eq.js.map +120 -0
- package/dist/{chunk-bk9svbcq.js → chunk-7mc2wkre.js} +386 -86
- package/dist/chunk-7mc2wkre.js.map +50 -0
- package/dist/{chunk-6rqgmkde.js → chunk-7z5p905k.js} +335 -703
- package/dist/chunk-7z5p905k.js.map +22 -0
- package/dist/{chunk-yxd3nnqt.js → chunk-9mab3dvg.js} +26 -2
- package/dist/chunk-9mab3dvg.js.map +11 -0
- package/dist/chunk-9wr3yajk.js +42 -0
- package/dist/chunk-9wr3yajk.js.map +10 -0
- package/dist/chunk-az47zep4.js +41 -0
- package/dist/chunk-az47zep4.js.map +10 -0
- package/dist/{chunk-s7jg7pmn.js → chunk-bab05bhg.js} +1 -1
- package/dist/{chunk-858emn8m.js → chunk-bktev1ds.js} +14 -11
- package/dist/{chunk-858emn8m.js.map → chunk-bktev1ds.js.map} +3 -3
- package/dist/{chunk-dhcv7yxc.js → chunk-c0vk1djt.js} +5 -3
- package/dist/chunk-c0vk1djt.js.map +11 -0
- package/dist/chunk-c69nj7se.js +3 -0
- package/dist/{chunk-7n30ybym.js.map → chunk-c69nj7se.js.map} +1 -1
- package/dist/{chunk-q5e5tv4b.js → chunk-c844dkwd.js} +1 -1
- package/dist/{chunk-g257jwnc.js → chunk-cdk3egjj.js} +17 -4
- package/dist/chunk-cdk3egjj.js.map +12 -0
- package/dist/chunk-cswhawa2.js +113 -0
- package/dist/chunk-cswhawa2.js.map +10 -0
- package/dist/{chunk-cfj9dfbb.js → chunk-d2m879s4.js} +2 -2
- package/dist/{chunk-arns890k.js → chunk-d7vyc7k6.js} +2 -2
- package/dist/chunk-d7vyc7k6.js.map +10 -0
- package/dist/{chunk-q7gn29y3.js → chunk-dp0cdtj2.js} +2 -2
- package/dist/{chunk-6x0pqh32.js → chunk-e5wf5vz0.js} +3 -1
- package/dist/chunk-e5wf5vz0.js.map +10 -0
- package/dist/{chunk-cn0fwwhy.js → chunk-efmm01gj.js} +108 -1045
- package/dist/chunk-efmm01gj.js.map +18 -0
- package/dist/{chunk-918wwnaa.js → chunk-ezne9wc9.js} +1224 -430
- package/dist/chunk-ezne9wc9.js.map +71 -0
- package/dist/{chunk-tbc1ngpd.js → chunk-fe8zwt8b.js} +58 -12
- package/dist/{chunk-tbc1ngpd.js.map → chunk-fe8zwt8b.js.map} +5 -4
- package/dist/{chunk-br3k6qbf.js → chunk-fm62y49k.js} +1 -1
- package/dist/{chunk-nq6gpjt7.js → chunk-fntqb7qy.js} +30 -4
- package/dist/{chunk-nq6gpjt7.js.map → chunk-fntqb7qy.js.map} +5 -5
- package/dist/{chunk-1cc1xaf3.js → chunk-fp2kq35z.js} +26 -10
- package/dist/{chunk-1cc1xaf3.js.map → chunk-fp2kq35z.js.map} +5 -5
- package/dist/{chunk-vvxtn22d.js → chunk-g663fahq.js} +2 -2
- package/dist/{chunk-k43ct2ke.js → chunk-gvj5cd3b.js} +16 -9
- package/dist/chunk-gvj5cd3b.js.map +12 -0
- package/dist/{chunk-rmakanzx.js → chunk-h33shhq6.js} +5 -5
- package/dist/{chunk-nn5xnx3s.js → chunk-h3pbv7n8.js} +1738 -38
- package/dist/chunk-h3pbv7n8.js.map +48 -0
- package/dist/chunk-hn2r7z41.js.map +1 -1
- package/dist/{chunk-pbcbn83d.js → chunk-hqsp2sx4.js} +54 -8
- package/dist/chunk-hqsp2sx4.js.map +14 -0
- package/dist/{chunk-d09e3rax.js → chunk-hwarjrgf.js} +1 -1
- package/dist/{chunk-vf57cr4t.js → chunk-hyesv9dv.js} +1 -1
- package/dist/chunk-hz5d43gn.js +45 -0
- package/dist/chunk-hz5d43gn.js.map +10 -0
- package/dist/{chunk-91mg3nj9.js → chunk-j936th07.js} +86 -41
- package/dist/chunk-j936th07.js.map +12 -0
- package/dist/chunk-kcqpk9w1.js +75 -0
- package/dist/chunk-kcqpk9w1.js.map +10 -0
- package/dist/{chunk-5vems3nx.js → chunk-m2nevja0.js} +2 -2
- package/dist/{chunk-x9v4cx1d.js → chunk-m36fw8ft.js} +1 -1
- package/dist/{chunk-a40ad1ft.js → chunk-mbsbxarb.js} +1 -1
- package/dist/chunk-mzx71snp.js +129 -0
- package/dist/chunk-mzx71snp.js.map +10 -0
- package/dist/{chunk-6aawea28.js → chunk-n8q5j6y5.js} +1 -1
- package/dist/{chunk-d7dnxdep.js → chunk-n9zpx9c6.js} +4 -4
- package/dist/{chunk-xvsc5m8n.js → chunk-npcr0228.js} +1 -1
- package/dist/chunk-nydf3dbe.js +663 -0
- package/dist/chunk-nydf3dbe.js.map +13 -0
- package/dist/chunk-pdt5cw8z.js +233 -0
- package/dist/chunk-pdt5cw8z.js.map +11 -0
- package/dist/{chunk-rj69qcrd.js → chunk-pgrf64hp.js} +55 -7
- package/dist/chunk-pgrf64hp.js.map +12 -0
- package/dist/{chunk-y5tah2kf.js → chunk-q4pmvkg0.js} +1 -1
- package/dist/chunk-qhqgp4jf.js +1418 -0
- package/dist/chunk-qhqgp4jf.js.map +22 -0
- package/dist/{chunk-48qjhh6v.js → chunk-qx00vjrj.js} +19 -60
- package/dist/chunk-qx00vjrj.js.map +13 -0
- package/dist/{chunk-5948n82c.js → chunk-r6szek0x.js} +184 -7
- package/dist/chunk-r6szek0x.js.map +10 -0
- package/dist/{chunk-v4jbb3rs.js → chunk-rap5w0x0.js} +156 -2
- package/dist/chunk-rap5w0x0.js.map +10 -0
- package/dist/{chunk-pfp1txq2.js → chunk-sgx82nnt.js} +5 -31
- package/dist/{chunk-pfp1txq2.js.map → chunk-sgx82nnt.js.map} +3 -4
- package/dist/{chunk-bkpke1sg.js → chunk-t5608tkq.js} +3 -1
- package/dist/{chunk-bkpke1sg.js.map → chunk-t5608tkq.js.map} +3 -3
- package/dist/{chunk-29yx306f.js → chunk-tdxfsg1c.js} +507 -265
- package/dist/chunk-tdxfsg1c.js.map +23 -0
- package/dist/{chunk-d5rjr8c0.js → chunk-vabga7fk.js} +1 -1
- package/dist/{chunk-dhdha526.js → chunk-vhbw5sqm.js} +26 -2
- package/dist/chunk-vhbw5sqm.js.map +10 -0
- package/dist/{chunk-e6k4thh5.js → chunk-vpgwq5nf.js} +98 -12
- package/dist/chunk-vpgwq5nf.js.map +21 -0
- package/dist/{chunk-61y5xs4p.js → chunk-vyt322b6.js} +69 -50
- package/dist/{chunk-61y5xs4p.js.map → chunk-vyt322b6.js.map} +4 -4
- package/dist/chunk-waqk73p1.js +2380 -0
- package/dist/chunk-waqk73p1.js.map +23 -0
- package/dist/chunk-wsc1brye.js +27 -0
- package/dist/chunk-wsc1brye.js.map +10 -0
- package/dist/{chunk-96yw3pwd.js → chunk-y7dbmaqh.js} +28 -2
- package/dist/chunk-y7dbmaqh.js.map +10 -0
- package/dist/{chunk-6vb4st8k.js → chunk-yc9ners4.js} +120 -19
- package/dist/{chunk-6vb4st8k.js.map → chunk-yc9ners4.js.map} +8 -8
- package/dist/{chunk-dvd2fp9q.js → chunk-zbc929zg.js} +28 -4
- package/dist/chunk-zbc929zg.js.map +13 -0
- package/dist/chunk-zrvhsq7f.js +37 -0
- package/dist/chunk-zrvhsq7f.js.map +10 -0
- package/dist/datasets/write.js +5 -5
- package/dist/error-reporting/internal.js +3 -3
- package/dist/errors/catalog.d.ts +26 -0
- package/dist/errors/catalog.d.ts.map +1 -1
- package/dist/errors/internal.d.ts.map +1 -1
- package/dist/errors/internal.js +1 -1
- package/dist/events/definitions.d.ts +7 -0
- package/dist/events/definitions.d.ts.map +1 -1
- package/dist/events/execution.d.ts.map +1 -1
- package/dist/events/index.d.ts +2 -3
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +8 -10
- package/dist/events/index.js.map +1 -1
- package/dist/events/scope.d.ts.map +1 -1
- package/dist/events/scope.js +1 -1
- package/dist/events/selectors/builder.d.ts +12 -1
- package/dist/events/selectors/builder.d.ts.map +1 -1
- package/dist/events/selectors/index.d.ts +2 -2
- package/dist/events/selectors/index.d.ts.map +1 -1
- package/dist/events/selectors/index.js +2 -2
- package/dist/events/selectors/types.d.ts +19 -3
- package/dist/events/selectors/types.d.ts.map +1 -1
- package/dist/events/service.d.ts +17 -2
- package/dist/events/service.d.ts.map +1 -1
- package/dist/events/types/index.d.ts +3 -1
- package/dist/events/types/index.d.ts.map +1 -1
- package/dist/events/types/users.d.ts +63 -0
- package/dist/events/types/users.d.ts.map +1 -0
- package/dist/events/view-conditions.d.ts +34 -0
- package/dist/events/view-conditions.d.ts.map +1 -0
- package/dist/execution/agent.d.ts +15 -0
- package/dist/execution/agent.d.ts.map +1 -1
- package/dist/execution/agent.js +63 -57
- package/dist/execution/agent.js.map +1 -1
- package/dist/execution/authorization.d.ts.map +1 -1
- package/dist/execution/authorized-object-reader.d.ts +51 -2
- package/dist/execution/authorized-object-reader.d.ts.map +1 -1
- package/dist/execution/lineage.d.ts +7 -0
- package/dist/execution/lineage.d.ts.map +1 -0
- package/dist/execution/object-reader-ontology.d.ts +2 -2
- package/dist/execution/object-reader-ontology.d.ts.map +1 -1
- package/dist/execution/object-reader-security.d.ts +24 -3
- package/dist/execution/object-reader-security.d.ts.map +1 -1
- package/dist/execution/object-reader-users.d.ts +20 -0
- package/dist/execution/object-reader-users.d.ts.map +1 -0
- package/dist/execution/preparation.d.ts +23 -0
- package/dist/execution/preparation.d.ts.map +1 -0
- package/dist/execution/primitive.js +61 -57
- package/dist/execution/primitive.js.map +1 -1
- package/dist/execution/request.d.ts +2 -1
- package/dist/execution/request.d.ts.map +1 -1
- package/dist/execution/request.js +64 -56
- package/dist/execution/request.js.map +3 -3
- package/dist/execution/unique-lookup.d.ts +14 -0
- package/dist/execution/unique-lookup.d.ts.map +1 -0
- package/dist/execution/visible-objects.d.ts +12 -0
- package/dist/execution/visible-objects.d.ts.map +1 -0
- package/dist/http/api-routes.d.ts +17 -0
- package/dist/http/api-routes.d.ts.map +1 -1
- package/dist/http/index.js +1 -1
- package/dist/index.d.ts +32 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +137 -126
- package/dist/index.js.map +1 -1
- package/dist/lake-storage/index.js +5 -5
- package/dist/materialization/errors.d.ts +25 -0
- package/dist/materialization/errors.d.ts.map +1 -1
- package/dist/materialization/event-envelopes.d.ts +5 -0
- package/dist/materialization/event-envelopes.d.ts.map +1 -1
- package/dist/materialization/index.d.ts +1 -1
- package/dist/materialization/index.d.ts.map +1 -1
- package/dist/materialization/index.js +14 -8
- package/dist/materialization/index.js.map +1 -1
- package/dist/materialization/model.d.ts +20 -2
- package/dist/materialization/model.d.ts.map +1 -1
- package/dist/materializer/edits/commit.d.ts.map +1 -1
- package/dist/materializer/edits/load-state.d.ts +5 -1
- package/dist/materializer/edits/load-state.d.ts.map +1 -1
- package/dist/materializer/edits/plan.d.ts.map +1 -1
- package/dist/materializer/edits/unique-values.d.ts +47 -0
- package/dist/materializer/edits/unique-values.d.ts.map +1 -0
- package/dist/materializer/edits/working-state.d.ts +6 -1
- package/dist/materializer/edits/working-state.d.ts.map +1 -1
- package/dist/materializer/execution/work-records.d.ts +7 -1
- package/dist/materializer/execution/work-records.d.ts.map +1 -1
- package/dist/materializer/index.js +45 -41
- package/dist/materializer/index.js.map +1 -1
- package/dist/materializer/projections/replacement-plan.d.ts.map +1 -1
- package/dist/materializer/projections/source-materialization.d.ts +1 -0
- package/dist/materializer/projections/source-materialization.d.ts.map +1 -1
- package/dist/materializer/shared/normalize.d.ts.map +1 -1
- package/dist/materializer/shared/projection-run.d.ts +0 -1
- package/dist/materializer/shared/projection-run.d.ts.map +1 -1
- package/dist/materializer/telemetry/plan.d.ts.map +1 -1
- package/dist/models/audio/catalog.d.ts +13 -1
- package/dist/models/audio/catalog.d.ts.map +1 -1
- package/dist/models/audio/errors.d.ts +6 -1
- package/dist/models/audio/errors.d.ts.map +1 -1
- package/dist/models/audio/runtime.d.ts.map +1 -1
- package/dist/models/audio/speech.d.ts +8 -0
- package/dist/models/audio/speech.d.ts.map +1 -0
- package/dist/models/audio/types.d.ts +93 -0
- package/dist/models/audio/types.d.ts.map +1 -1
- package/dist/models/calls.d.ts +27 -0
- package/dist/models/calls.d.ts.map +1 -0
- package/dist/models/catalog-index.d.ts +7 -4
- package/dist/models/catalog-index.d.ts.map +1 -1
- package/dist/models/catalog.d.ts +55 -3
- package/dist/models/catalog.d.ts.map +1 -1
- package/dist/models/decision/runtime.d.ts +6 -1
- package/dist/models/decision/runtime.d.ts.map +1 -1
- package/dist/models/decision/validation.d.ts +4 -1
- package/dist/models/decision/validation.d.ts.map +1 -1
- package/dist/models/definitions.d.ts +23 -1
- package/dist/models/definitions.d.ts.map +1 -1
- package/dist/models/events.d.ts +12 -1
- package/dist/models/events.d.ts.map +1 -1
- package/dist/models/execution/binding.d.ts +3 -1
- package/dist/models/execution/binding.d.ts.map +1 -1
- package/dist/models/execution/index.d.ts +1 -0
- package/dist/models/execution/index.d.ts.map +1 -1
- package/dist/models/execution/index.js +44 -34
- package/dist/models/execution/index.js.map +1 -1
- package/dist/models/execution/model-call-accounting.d.ts.map +1 -1
- package/dist/models/execution/model-call-recorder.d.ts +3 -0
- package/dist/models/execution/model-call-recorder.d.ts.map +1 -1
- package/dist/models/execution/usage.d.ts.map +1 -1
- package/dist/models/execution.d.ts +4 -2
- package/dist/models/execution.d.ts.map +1 -1
- package/dist/models/generation-types.d.ts +8 -1
- package/dist/models/generation-types.d.ts.map +1 -1
- package/dist/models/image/catalog.d.ts +13 -0
- package/dist/models/image/catalog.d.ts.map +1 -0
- package/dist/models/image/errors.d.ts +8 -0
- package/dist/models/image/errors.d.ts.map +1 -0
- package/dist/models/image/runtime.d.ts +8 -0
- package/dist/models/image/runtime.d.ts.map +1 -0
- package/dist/models/image/types.d.ts +103 -0
- package/dist/models/image/types.d.ts.map +1 -0
- package/dist/models/index.d.ts +12 -8
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +17 -7
- package/dist/models/index.js.map +1 -1
- package/dist/models/input-file.d.ts +9 -0
- package/dist/models/input-file.d.ts.map +1 -0
- package/dist/models/language-model.d.ts +13 -0
- package/dist/models/language-model.d.ts.map +1 -1
- package/dist/models/pricing.d.ts +25 -10
- package/dist/models/pricing.d.ts.map +1 -1
- package/dist/models/rate-card.d.ts +44 -6
- package/dist/models/rate-card.d.ts.map +1 -1
- package/dist/objects/conditional-writes.d.ts +37 -0
- package/dist/objects/conditional-writes.d.ts.map +1 -0
- package/dist/objects/execution.d.ts +2 -0
- package/dist/objects/execution.d.ts.map +1 -1
- package/dist/objects/index.d.ts +1 -0
- package/dist/objects/index.d.ts.map +1 -1
- package/dist/objects/index.js +68 -58
- package/dist/objects/index.js.map +1 -1
- package/dist/objects/link/authorization.d.ts +3 -0
- package/dist/objects/link/authorization.d.ts.map +1 -1
- package/dist/objects/link/endpoints.d.ts +21 -2
- package/dist/objects/link/endpoints.d.ts.map +1 -1
- package/dist/objects/link/remove.d.ts.map +1 -1
- package/dist/objects/link/upsert-batch.d.ts.map +1 -1
- package/dist/objects/link/upsert.d.ts.map +1 -1
- package/dist/objects/materializer-adapter.d.ts +13 -4
- package/dist/objects/materializer-adapter.d.ts.map +1 -1
- package/dist/objects/object/delete.d.ts +3 -0
- package/dist/objects/object/delete.d.ts.map +1 -1
- package/dist/objects/object/upsert-batch.d.ts.map +1 -1
- package/dist/objects/object/upsert.d.ts.map +1 -1
- package/dist/objects/query/current-user.d.ts +17 -0
- package/dist/objects/query/current-user.d.ts.map +1 -0
- package/dist/objects/query/executor.d.ts +14 -0
- package/dist/objects/query/executor.d.ts.map +1 -1
- package/dist/objects/query/index.d.ts +2 -2
- package/dist/objects/query/index.d.ts.map +1 -1
- package/dist/objects/query/index.js +49 -44
- package/dist/objects/query/index.js.map +1 -1
- package/dist/objects/query/ir.d.ts +19 -1
- package/dist/objects/query/ir.d.ts.map +1 -1
- package/dist/objects/query/matches-predicate.d.ts +9 -0
- package/dist/objects/query/matches-predicate.d.ts.map +1 -0
- package/dist/objects/query/normalize.d.ts.map +1 -1
- package/dist/objects/query/user-expansions.d.ts +27 -0
- package/dist/objects/query/user-expansions.d.ts.map +1 -0
- package/dist/objects/query/validate.d.ts.map +1 -1
- package/dist/objects/runtime-batch.d.ts +3 -1
- package/dist/objects/runtime-batch.d.ts.map +1 -1
- package/dist/objects/sdk/object-set.d.ts.map +1 -1
- package/dist/objects/sdk/query-executor.d.ts +6 -0
- package/dist/objects/sdk/query-executor.d.ts.map +1 -1
- package/dist/objects/serialize.d.ts +39 -0
- package/dist/objects/serialize.d.ts.map +1 -0
- package/dist/objects/unique-violation.d.ts +22 -0
- package/dist/objects/unique-violation.d.ts.map +1 -0
- package/dist/ontology/builders.d.ts +3 -1
- package/dist/ontology/builders.d.ts.map +1 -1
- package/dist/ontology/index.d.ts +2 -2
- package/dist/ontology/index.d.ts.map +1 -1
- package/dist/ontology/index.js +11 -7
- package/dist/ontology/index.js.map +1 -1
- package/dist/ontology/internal.js +7 -5
- package/dist/ontology/internal.js.map +3 -3
- package/dist/ontology/json-schema.d.ts.map +1 -1
- package/dist/ontology/primitives.d.ts +3 -0
- package/dist/ontology/primitives.d.ts.map +1 -1
- package/dist/ontology/registry.d.ts +6 -0
- package/dist/ontology/registry.d.ts.map +1 -1
- package/dist/ontology/types.d.ts +9 -0
- package/dist/ontology/types.d.ts.map +1 -1
- package/dist/ontology/unique-values.d.ts +26 -0
- package/dist/ontology/unique-values.d.ts.map +1 -0
- package/dist/ontology/user-ref.d.ts +23 -0
- package/dist/ontology/user-ref.d.ts.map +1 -1
- package/dist/ontology/validation/properties.d.ts.map +1 -1
- package/dist/ontology/validation/schema.d.ts.map +1 -1
- package/dist/pipelines/index.js +43 -40
- package/dist/pipelines/index.js.map +1 -1
- package/dist/projections/internal.js +36 -33
- package/dist/projections/internal.js.map +1 -1
- package/dist/projections/registry.d.ts +4 -0
- package/dist/projections/registry.d.ts.map +1 -1
- package/dist/projections/revision.d.ts +15 -0
- package/dist/projections/revision.d.ts.map +1 -1
- package/dist/projections/run-dispatch.d.ts.map +1 -1
- package/dist/projections/types.d.ts +2 -0
- package/dist/projections/types.d.ts.map +1 -1
- package/dist/query.d.ts +4 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +2 -2
- package/dist/rules/execution.d.ts.map +1 -1
- package/dist/runtime/ai-cost.d.ts +2 -0
- package/dist/runtime/ai-cost.d.ts.map +1 -1
- package/dist/runtime/ai-usage.d.ts +7 -0
- package/dist/runtime/ai-usage.d.ts.map +1 -1
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/internal.js +42 -38
- package/dist/runtime/internal.js.map +1 -1
- package/dist/runtime/resolve-definitions.d.ts.map +1 -1
- package/dist/runtime/sixb.d.ts +2 -0
- package/dist/runtime/sixb.d.ts.map +1 -1
- package/dist/runtime/types.d.ts +66 -8
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/sandboxes/index.js +7 -6
- package/dist/sandboxes/index.js.map +1 -1
- package/dist/schedules/builders.d.ts.map +1 -1
- package/dist/schedules/index.js +3 -3
- package/dist/schedules/runtime.d.ts.map +1 -1
- package/dist/schedules/validation.d.ts.map +1 -1
- package/dist/security/grants.d.ts +12 -4
- 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/internal.js +1 -1
- package/dist/security/project.d.ts +4 -1
- package/dist/security/project.d.ts.map +1 -1
- package/dist/security/public.js +2 -2
- package/dist/security/registry.d.ts +6 -0
- package/dist/security/registry.d.ts.map +1 -1
- package/dist/security/types.d.ts +47 -9
- package/dist/security/types.d.ts.map +1 -1
- package/dist/security/validation.d.ts.map +1 -1
- package/dist/security/view-conditions.d.ts +37 -0
- package/dist/security/view-conditions.d.ts.map +1 -0
- package/dist/shares/execution.d.ts.map +1 -1
- package/dist/shares/internal.js +34 -31
- package/dist/shares/internal.js.map +2 -2
- package/dist/storage/action-runs/failure.js +2 -2
- package/dist/storage/action-runs/provider.js +1 -1
- package/dist/storage/action-runs/types.d.ts +1 -1
- package/dist/storage/action-runs/types.d.ts.map +1 -1
- package/dist/storage/agents/errors.d.ts +3 -1
- package/dist/storage/agents/errors.d.ts.map +1 -1
- package/dist/storage/agents/in-memory.d.ts +120 -3
- package/dist/storage/agents/in-memory.d.ts.map +1 -1
- package/dist/storage/agents/index.d.ts +2 -2
- package/dist/storage/agents/index.d.ts.map +1 -1
- package/dist/storage/agents/provider.d.ts +154 -4
- package/dist/storage/agents/provider.d.ts.map +1 -1
- package/dist/storage/agents/provider.js +60 -5
- package/dist/storage/agents/provider.js.map +1 -1
- package/dist/storage/agents/types.d.ts +565 -13
- package/dist/storage/agents/types.d.ts.map +1 -1
- package/dist/storage/ai-cost/analytics.d.ts +10 -1
- package/dist/storage/ai-cost/analytics.d.ts.map +1 -1
- package/dist/storage/ai-cost/groups.d.ts +9 -0
- package/dist/storage/ai-cost/groups.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 -1
- package/dist/storage/ai-cost/provider.d.ts.map +1 -1
- package/dist/storage/ai-cost/provider.js +11 -5
- package/dist/storage/ai-cost/provider.js.map +1 -1
- package/dist/storage/ai-cost/types.d.ts +14 -2
- package/dist/storage/ai-cost/types.d.ts.map +1 -1
- package/dist/storage/ai-cost/validation.d.ts.map +1 -1
- package/dist/storage/ai-limits/enforcement.js +5 -4
- package/dist/storage/ai-limits/enforcement.js.map +1 -1
- package/dist/storage/ai-limits/provider.d.ts +1 -1
- package/dist/storage/ai-limits/provider.d.ts.map +1 -1
- package/dist/storage/ai-limits/provider.js +3 -2
- package/dist/storage/ai-limits/provider.js.map +1 -1
- package/dist/storage/ai-usage/in-memory.d.ts +5 -1
- package/dist/storage/ai-usage/in-memory.d.ts.map +1 -1
- package/dist/storage/ai-usage/index.d.ts +2 -2
- package/dist/storage/ai-usage/index.d.ts.map +1 -1
- package/dist/storage/ai-usage/record.d.ts +5 -1
- package/dist/storage/ai-usage/record.d.ts.map +1 -1
- package/dist/storage/ai-usage/types.d.ts +33 -0
- package/dist/storage/ai-usage/types.d.ts.map +1 -1
- package/dist/storage/ai-usage/usage.d.ts +2 -0
- package/dist/storage/ai-usage/usage.d.ts.map +1 -1
- package/dist/storage/artifacts/errors.d.ts +12 -2
- package/dist/storage/artifacts/errors.d.ts.map +1 -1
- package/dist/storage/artifacts/in-memory.d.ts +23 -2
- package/dist/storage/artifacts/in-memory.d.ts.map +1 -1
- package/dist/storage/artifacts/index.d.ts +2 -2
- package/dist/storage/artifacts/index.d.ts.map +1 -1
- package/dist/storage/artifacts/record.d.ts +19 -2
- package/dist/storage/artifacts/record.d.ts.map +1 -1
- package/dist/storage/artifacts/types.d.ts +87 -8
- package/dist/storage/artifacts/types.d.ts.map +1 -1
- package/dist/storage/auth/in-memory/auth-storage.d.ts +3 -2
- package/dist/storage/auth/in-memory/auth-storage.d.ts.map +1 -1
- package/dist/storage/auth/in-memory/users.d.ts +7 -3
- package/dist/storage/auth/in-memory/users.d.ts.map +1 -1
- package/dist/storage/auth/index.d.ts +1 -1
- package/dist/storage/auth/index.d.ts.map +1 -1
- package/dist/storage/auth/types.d.ts +40 -9
- package/dist/storage/auth/types.d.ts.map +1 -1
- package/dist/storage/connector-connections/provider.js +1 -1
- package/dist/storage/executions/in-memory.d.ts +2 -1
- package/dist/storage/executions/in-memory.d.ts.map +1 -1
- package/dist/storage/executions/index.d.ts +1 -1
- package/dist/storage/executions/index.d.ts.map +1 -1
- package/dist/storage/executions/types.d.ts +15 -0
- package/dist/storage/executions/types.d.ts.map +1 -1
- package/dist/storage/file-upload-sessions/provider.js +15 -12
- package/dist/storage/file-upload-sessions/provider.js.map +1 -1
- package/dist/storage/index.d.ts +13 -11
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +50 -39
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/internal.d.ts +2 -2
- package/dist/storage/internal.d.ts.map +1 -1
- package/dist/storage/internal.js +19 -8
- package/dist/storage/internal.js.map +1 -1
- package/dist/storage/migrations/migrate-storage.d.ts +4 -1
- package/dist/storage/migrations/migrate-storage.d.ts.map +1 -1
- package/dist/storage/migrations/prepare-unique-properties.d.ts +18 -0
- package/dist/storage/migrations/prepare-unique-properties.d.ts.map +1 -0
- package/dist/storage/objects/guard.d.ts +1 -1
- package/dist/storage/objects/guard.d.ts.map +1 -1
- package/dist/storage/objects/in-memory/conditional-reader.d.ts +5 -0
- package/dist/storage/objects/in-memory/conditional-reader.d.ts.map +1 -0
- package/dist/storage/objects/in-memory/query.d.ts.map +1 -1
- package/dist/storage/objects/in-memory/read-scope.d.ts +3 -9
- package/dist/storage/objects/in-memory/read-scope.d.ts.map +1 -1
- package/dist/storage/objects/in-memory/read-source.d.ts +10 -1
- package/dist/storage/objects/in-memory/read-source.d.ts.map +1 -1
- package/dist/storage/objects/in-memory/scoped-reader.d.ts +14 -0
- package/dist/storage/objects/in-memory/scoped-reader.d.ts.map +1 -0
- package/dist/storage/objects/in-memory/selected-reader.d.ts.map +1 -1
- package/dist/storage/objects/in-memory/storage.d.ts +36 -1
- package/dist/storage/objects/in-memory/storage.d.ts.map +1 -1
- package/dist/storage/objects/index.d.ts +2 -2
- package/dist/storage/objects/index.d.ts.map +1 -1
- package/dist/storage/objects/read-scope.d.ts +9 -1
- package/dist/storage/objects/read-scope.d.ts.map +1 -1
- package/dist/storage/objects/types.d.ts +64 -1
- package/dist/storage/objects/types.d.ts.map +1 -1
- package/dist/storage/ontology/in-memory/index.d.ts +2 -0
- package/dist/storage/ontology/in-memory/index.d.ts.map +1 -1
- package/dist/storage/ontology/in-memory/materializations.d.ts +1 -0
- package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
- package/dist/storage/ontology/in-memory/replacement-plans.d.ts.map +1 -1
- package/dist/storage/ontology/in-memory/unique-values.d.ts +32 -0
- package/dist/storage/ontology/in-memory/unique-values.d.ts.map +1 -0
- package/dist/storage/ontology/index.d.ts +4 -1
- package/dist/storage/ontology/index.d.ts.map +1 -1
- package/dist/storage/ontology/materializations.d.ts +34 -1
- package/dist/storage/ontology/materializations.d.ts.map +1 -1
- package/dist/storage/ontology/provider-work.d.ts +15 -2
- package/dist/storage/ontology/provider-work.d.ts.map +1 -1
- package/dist/storage/ontology/provider.d.ts +1 -1
- package/dist/storage/ontology/provider.d.ts.map +1 -1
- package/dist/storage/ontology/provider.js +9 -4
- package/dist/storage/ontology/provider.js.map +1 -1
- package/dist/storage/ontology/unique-values.d.ts +54 -0
- package/dist/storage/ontology/unique-values.d.ts.map +1 -0
- package/dist/storage/operation-scope.d.ts +1 -1
- package/dist/storage/operation-scope.d.ts.map +1 -1
- package/dist/storage/operation-scope.js +1 -1
- package/dist/storage/projection-runs/in-memory.d.ts +0 -6
- package/dist/storage/projection-runs/in-memory.d.ts.map +1 -1
- package/dist/storage/projection-runs/provider.js +2 -2
- package/dist/storage/share-grants/provider.js +4 -3
- package/dist/storage/share-grants/provider.js.map +1 -1
- package/dist/storage/types.d.ts +2 -2
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/workflow-runs/provider.js +15 -12
- package/dist/storage/workflow-runs/provider.js.map +1 -1
- package/dist/syncs/index.js +42 -39
- package/dist/syncs/index.js.map +1 -1
- package/dist/testing/agent-approval-storage-contract.d.ts +17 -0
- package/dist/testing/agent-approval-storage-contract.d.ts.map +1 -0
- package/dist/testing/agent-memory-storage-contract.d.ts +12 -0
- package/dist/testing/agent-memory-storage-contract.d.ts.map +1 -0
- 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 +0 -1
- package/dist/testing/ai-limit-storage-contract.d.ts.map +1 -1
- package/dist/testing/ai-model-call-groups-contract.d.ts.map +1 -1
- package/dist/testing/ai-usage-storage-contract.d.ts.map +1 -1
- package/dist/testing/artifact-storage-contract.d.ts.map +1 -1
- package/dist/testing/auth-storage-contract.d.ts +13 -0
- package/dist/testing/auth-storage-contract.d.ts.map +1 -1
- package/dist/testing/broker-contract.d.ts +5 -0
- package/dist/testing/broker-contract.d.ts.map +1 -1
- package/dist/testing/effective-storage-contract.d.ts.map +1 -1
- package/dist/testing/execution-storage-contract.d.ts.map +1 -1
- package/dist/testing/file-upload-session-storage-contract.d.ts.map +1 -1
- package/dist/testing/index.d.ts +9 -5
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +7938 -3743
- package/dist/testing/index.js.map +29 -25
- package/dist/testing/lake-storage-contract.d.ts.map +1 -1
- package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
- package/dist/testing/object-conditional-read-scope-contract.d.ts +11 -0
- package/dist/testing/object-conditional-read-scope-contract.d.ts.map +1 -0
- package/dist/testing/object-query-contract.d.ts +0 -2
- package/dist/testing/object-query-contract.d.ts.map +1 -1
- package/dist/testing/ontology-storage-contract.d.ts.map +1 -1
- package/dist/testing/projection-run-storage-contract.d.ts.map +1 -1
- package/dist/testing/queues-contract.d.ts +5 -0
- package/dist/testing/queues-contract.d.ts.map +1 -1
- package/dist/testing/sandboxes-contract.d.ts.map +1 -1
- package/dist/testing/share-grant-storage-contract.d.ts.map +1 -1
- package/dist/testing/share-session-storage-contract.d.ts.map +1 -1
- package/dist/testing/unique-values-contract.d.ts +21 -0
- package/dist/testing/unique-values-contract.d.ts.map +1 -0
- package/dist/testing/webhook-execution.d.ts +0 -8
- package/dist/testing/webhook-execution.d.ts.map +1 -1
- package/dist/testing/webhook-run-storage-contract.d.ts.map +1 -1
- package/dist/users/execution.d.ts +40 -0
- package/dist/users/execution.d.ts.map +1 -0
- package/dist/users/index.d.ts +3 -0
- package/dist/users/index.d.ts.map +1 -0
- package/dist/webhooks/internal.js +34 -31
- package/dist/webhooks/internal.js.map +2 -2
- package/dist/workers/index.js +4 -6
- package/dist/workers/index.js.map +4 -4
- package/dist/workers/queue-worker.d.ts +0 -2
- package/dist/workers/queue-worker.d.ts.map +1 -1
- package/dist/workers/worker.d.ts +0 -2
- package/dist/workers/worker.d.ts.map +1 -1
- package/dist/workflows/builders.d.ts.map +1 -1
- package/dist/workflows/index.js +67 -63
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/request.d.ts +12 -1
- package/dist/workflows/request.d.ts.map +1 -1
- package/dist/workflows/types.d.ts +6 -2
- package/dist/workflows/types.d.ts.map +1 -1
- package/dist/workflows/validation.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/actions/commit-edits.ts +6 -1
- package/src/actions/execution.ts +42 -15
- package/src/actions/read-facade.ts +33 -0
- package/src/actions/request.ts +224 -71
- package/src/actions/run/context.ts +47 -1
- package/src/actions/run/execute.ts +13 -6
- package/src/actions/run/executor.ts +11 -2
- package/src/actions/run/normalize.ts +12 -2
- package/src/actions/run/phases.ts +2 -0
- package/src/actions/run/run-action.ts +12 -3
- package/src/actions/run/signals.ts +3 -9
- package/src/actions/run/types.ts +17 -1
- package/src/actions/run-authorization.ts +72 -0
- package/src/actions/types/context.ts +20 -3
- package/src/actions/validators.ts +19 -8
- package/src/activity/README.md +5 -2
- package/src/activity/timeline.ts +39 -78
- package/src/agents/accounting.ts +59 -0
- package/src/agents/adapters.ts +10 -0
- package/src/agents/agent-mail.ts +29 -0
- package/src/agents/api-gateway.ts +14 -3
- package/src/agents/approval-continuation.ts +48 -0
- package/src/agents/approval-executor.ts +318 -0
- package/src/agents/approval-outcome.ts +59 -0
- package/src/agents/approvals.ts +566 -0
- package/src/agents/authority.ts +24 -1
- package/src/agents/builders.ts +5 -3
- package/src/agents/cancel.ts +103 -0
- package/src/agents/child-question.ts +46 -0
- package/src/agents/children.ts +404 -0
- package/src/agents/context-compaction.ts +12 -0
- package/src/agents/errors.ts +31 -0
- package/src/agents/execution.ts +788 -90
- package/src/agents/fork.ts +158 -0
- package/src/agents/ids.ts +18 -6
- package/src/agents/index.ts +55 -0
- package/src/agents/memory-execution.ts +186 -0
- package/src/agents/memory.ts +178 -0
- package/src/agents/message.ts +57 -0
- package/src/agents/model-loop.ts +93 -6
- package/src/agents/model-routing.ts +193 -0
- package/src/agents/participants.ts +213 -0
- package/src/agents/reference.ts +2 -0
- package/src/agents/request.ts +398 -69
- package/src/agents/run-scope.ts +134 -0
- package/src/agents/streams/index.ts +5 -0
- package/src/agents/streams/internal.ts +1 -0
- package/src/agents/streams/protocol.ts +385 -7
- package/src/agents/subagent-runs.ts +41 -0
- package/src/agents/thread-access.ts +137 -0
- package/src/agents/tool-definition.ts +5 -3
- package/src/agents/types.ts +35 -10
- package/src/agents/validation.ts +2 -0
- package/src/artifacts/access.ts +125 -0
- package/src/artifacts/canvas.ts +369 -0
- package/src/artifacts/csv.ts +10 -0
- package/src/artifacts/errors.ts +12 -1
- package/src/artifacts/execution.ts +436 -36
- package/src/artifacts/formula/check.ts +171 -0
- package/src/artifacts/formula/evaluate.ts +288 -0
- package/src/artifacts/formula/index.ts +199 -0
- package/src/artifacts/formula/parser.ts +357 -0
- package/src/artifacts/frames/assets.ts +35 -19
- package/src/artifacts/frames/entries.ts +35 -0
- package/src/artifacts/frames/grants.ts +10 -9
- package/src/artifacts/frames/index.ts +8 -2
- package/src/artifacts/frames/kit.ts +191 -14
- package/src/artifacts/frames/probe.ts +66 -18
- package/src/artifacts/frames/protocol.ts +164 -10
- package/src/artifacts/frames/runtime.ts +273 -28
- package/src/artifacts/index.ts +66 -2
- package/src/artifacts/kinds.ts +1 -1
- package/src/artifacts/limits.ts +31 -0
- package/src/artifacts/live-sheet.ts +345 -0
- package/src/artifacts/outline.ts +34 -1
- package/src/artifacts/publish/index.ts +2 -0
- package/src/artifacts/publish/publish.ts +120 -34
- package/src/artifacts/publish/queries.ts +336 -0
- package/src/artifacts/publish/references.ts +18 -13
- package/src/artifacts/publish/validate/canvas.ts +118 -0
- package/src/artifacts/publish/validate/html.ts +78 -0
- package/src/artifacts/publish/validate/page.ts +65 -0
- package/src/artifacts/publish/validate/sheet.ts +115 -69
- package/src/artifacts/publish/validate/slides.ts +11 -63
- package/src/artifacts/queries.ts +512 -0
- package/src/artifacts/resolve.ts +20 -5
- package/src/artifacts/run-query.ts +212 -0
- package/src/artifacts/serialize-query.ts +25 -0
- package/src/artifacts/sheet-rules.ts +180 -0
- package/src/artifacts/tones.ts +20 -0
- package/src/artifacts/workbook.ts +374 -15
- package/src/auth/index.ts +4 -0
- package/src/auth/member-events.ts +114 -0
- package/src/auth/profile.ts +118 -0
- package/src/auth/runtime.ts +190 -9
- package/src/auth/strategy.ts +3 -0
- package/src/auth/types.ts +32 -0
- package/src/authorization/decision.ts +47 -0
- package/src/authorization/event-visibility.ts +17 -16
- package/src/authorization/grant-kinds.ts +32 -0
- package/src/authorization/index.ts +6 -1
- package/src/authorization/resolve.ts +58 -1
- package/src/authorization/run-visibility.ts +8 -1
- package/src/authorization/types.ts +14 -0
- package/src/errors/catalog.ts +26 -1
- package/src/errors/internal.ts +17 -8
- package/src/events/definitions.ts +26 -0
- package/src/events/execution.ts +43 -6
- package/src/events/index.ts +10 -1
- package/src/events/scope.ts +2 -0
- package/src/events/selectors/builder.ts +50 -0
- package/src/events/selectors/index.ts +4 -0
- package/src/events/selectors/types.ts +32 -1
- package/src/events/service.ts +55 -2
- package/src/events/types/index.ts +10 -0
- package/src/events/types/users.ts +73 -0
- package/src/events/view-conditions.ts +241 -0
- package/src/execution/agent.ts +25 -0
- package/src/execution/authorization.ts +70 -0
- package/src/execution/authorized-object-reader.ts +238 -32
- package/src/execution/lineage.ts +14 -0
- package/src/execution/object-reader-ontology.ts +11 -14
- package/src/execution/object-reader-security.ts +134 -10
- package/src/execution/object-reader-users.ts +122 -0
- package/src/execution/preparation.ts +78 -0
- package/src/execution/request.ts +2 -0
- package/src/execution/unique-lookup.ts +55 -0
- package/src/execution/visible-objects.ts +26 -0
- package/src/http/api-routes.ts +206 -7
- package/src/index.ts +99 -2
- package/src/materialization/errors.ts +37 -0
- package/src/materialization/event-envelopes.ts +11 -3
- package/src/materialization/index.ts +1 -0
- package/src/materialization/model.ts +24 -4
- package/src/materializer/README.md +7 -1
- package/src/materializer/edits/commit.ts +56 -12
- package/src/materializer/edits/load-state.ts +15 -7
- package/src/materializer/edits/operations.ts +12 -0
- package/src/materializer/edits/plan.ts +2 -0
- package/src/materializer/edits/unique-values.ts +255 -0
- package/src/materializer/edits/working-state.ts +8 -1
- package/src/materializer/execution/work-records.ts +47 -0
- package/src/materializer/projections/finish-run.ts +0 -1
- package/src/materializer/projections/replace.ts +1 -1
- package/src/materializer/projections/replacement-plan.ts +4 -1
- package/src/materializer/projections/source-materialization.ts +2 -1
- package/src/materializer/shared/normalize.ts +37 -6
- package/src/materializer/shared/projection-run.ts +1 -2
- package/src/materializer/telemetry/append.ts +14 -17
- package/src/materializer/telemetry/plan.ts +2 -0
- package/src/models/audio/catalog.ts +89 -10
- package/src/models/audio/errors.ts +18 -1
- package/src/models/audio/runtime.ts +10 -13
- package/src/models/audio/speech.ts +261 -0
- package/src/models/audio/types.ts +97 -0
- package/src/models/calls.ts +100 -0
- package/src/models/catalog-index.ts +21 -2
- package/src/models/catalog.ts +211 -35
- package/src/models/decision/runtime.ts +21 -22
- package/src/models/decision/validation.ts +4 -1
- package/src/models/definitions.ts +57 -8
- package/src/models/events.ts +72 -1
- package/src/models/execution/README.md +34 -5
- package/src/models/execution/binding.ts +3 -1
- package/src/models/execution/embedding.ts +1 -0
- package/src/models/execution/index.ts +5 -0
- package/src/models/execution/model-call-accounting.ts +3 -1
- package/src/models/execution/model-call-recorder.ts +29 -1
- package/src/models/execution/usage.ts +8 -0
- package/src/models/execution.ts +20 -22
- package/src/models/generation-types.ts +8 -1
- package/src/models/image/catalog.ts +89 -0
- package/src/models/image/errors.ts +19 -0
- package/src/models/image/runtime.ts +335 -0
- package/src/models/image/types.ts +111 -0
- package/src/models/index.ts +38 -4
- package/src/models/{audio/file.ts → input-file.ts} +22 -13
- package/src/models/language-model.ts +13 -0
- package/src/models/pricing.ts +263 -42
- package/src/models/rate-card.ts +161 -12
- package/src/objects/authorized-ontology-view.ts +1 -0
- package/src/objects/conditional-writes.ts +109 -0
- package/src/objects/execution.ts +4 -0
- package/src/objects/index.ts +8 -0
- package/src/objects/link/authorization.ts +12 -3
- package/src/objects/link/endpoints.ts +42 -11
- package/src/objects/link/remove.ts +25 -10
- package/src/objects/link/upsert-batch.ts +2 -0
- package/src/objects/link/upsert.ts +18 -12
- package/src/objects/materializer-adapter.ts +55 -18
- package/src/objects/object/delete.ts +24 -7
- package/src/objects/object/upsert-batch.ts +44 -14
- package/src/objects/object/upsert.ts +23 -5
- package/src/objects/query/current-user.ts +76 -0
- package/src/objects/query/executor.ts +39 -103
- package/src/objects/query/explain.ts +20 -7
- package/src/objects/query/index.ts +2 -0
- package/src/objects/query/ir.ts +20 -0
- package/src/objects/query/links.ts +8 -0
- package/src/objects/query/matches-predicate.ts +108 -0
- package/src/objects/query/normalize.ts +50 -19
- package/src/objects/query/scalar-values.ts +19 -3
- package/src/objects/query/user-expansions.ts +65 -0
- package/src/objects/query/validate.ts +248 -10
- package/src/objects/runtime-batch.ts +8 -2
- package/src/objects/sdk/object-set.ts +12 -1
- package/src/objects/sdk/query-builder.ts +39 -8
- package/src/objects/sdk/query-executor.ts +6 -0
- package/src/objects/serialize.ts +79 -0
- package/src/objects/unique-violation.ts +59 -0
- package/src/objects/vectors/handle.ts +3 -3
- package/src/ontology/builders.ts +3 -0
- package/src/ontology/docs-markdown.ts +1 -0
- package/src/ontology/index.ts +2 -2
- package/src/ontology/json-schema.ts +4 -0
- package/src/ontology/primitives.ts +21 -8
- package/src/ontology/registry.ts +16 -0
- package/src/ontology/types.ts +9 -0
- package/src/ontology/unique-values.ts +84 -0
- package/src/ontology/user-ref.ts +39 -0
- package/src/ontology/validation/properties.ts +43 -0
- package/src/ontology/validation/schema.ts +9 -1
- package/src/projections/registry.ts +16 -10
- package/src/projections/revision.ts +112 -45
- package/src/projections/run-dispatch.ts +38 -25
- package/src/projections/types.ts +2 -0
- package/src/query.ts +5 -0
- package/src/rules/execution.ts +43 -11
- package/src/runtime/ai-cost.ts +30 -0
- package/src/runtime/ai-usage.ts +32 -1
- package/src/runtime/host.ts +18 -1
- package/src/runtime/index.ts +2 -0
- package/src/runtime/resolve-definitions.ts +3 -0
- package/src/runtime/sixb.ts +35 -8
- package/src/runtime/types.ts +99 -9
- package/src/schedules/builders.ts +3 -1
- package/src/schedules/runtime.ts +6 -0
- package/src/schedules/validation.ts +23 -1
- package/src/security/README.md +62 -0
- package/src/security/grants.ts +155 -10
- package/src/security/index.ts +3 -1
- package/src/security/project.ts +6 -1
- package/src/security/registry.ts +32 -7
- package/src/security/types.ts +54 -9
- package/src/security/validation.ts +27 -11
- package/src/security/view-conditions.ts +215 -0
- package/src/shares/execution.ts +43 -10
- package/src/storage/action-runs/types.ts +2 -0
- package/src/storage/agents/errors.ts +3 -0
- package/src/storage/agents/in-memory.ts +779 -32
- package/src/storage/agents/index.ts +42 -0
- package/src/storage/agents/provider.ts +733 -8
- package/src/storage/agents/types.ts +620 -12
- package/src/storage/ai-cost/analytics.ts +60 -7
- package/src/storage/ai-cost/codec.ts +6 -1
- package/src/storage/ai-cost/groups.ts +44 -1
- package/src/storage/ai-cost/index.ts +1 -0
- package/src/storage/ai-cost/provider.ts +2 -0
- package/src/storage/ai-cost/types.ts +18 -1
- package/src/storage/ai-cost/validation.ts +39 -12
- package/src/storage/ai-limits/provider.ts +4 -7
- package/src/storage/ai-usage/in-memory.ts +28 -1
- package/src/storage/ai-usage/index.ts +9 -1
- package/src/storage/ai-usage/record.ts +44 -7
- package/src/storage/ai-usage/types.ts +38 -0
- package/src/storage/ai-usage/usage.ts +15 -1
- package/src/storage/artifacts/errors.ts +13 -1
- package/src/storage/artifacts/in-memory.ts +156 -8
- package/src/storage/artifacts/index.ts +6 -1
- package/src/storage/artifacts/record.ts +61 -1
- package/src/storage/artifacts/types.ts +92 -8
- package/src/storage/auth/in-memory/auth-storage.ts +27 -2
- package/src/storage/auth/in-memory/users.ts +40 -6
- package/src/storage/auth/index.ts +1 -0
- package/src/storage/auth/types.ts +43 -7
- package/src/storage/executions/in-memory.ts +32 -0
- package/src/storage/executions/index.ts +2 -0
- package/src/storage/executions/types.ts +17 -0
- package/src/storage/index.ts +69 -1
- package/src/storage/internal.ts +9 -1
- package/src/storage/migrations/migrate-storage.ts +8 -1
- package/src/storage/migrations/prepare-unique-properties.ts +161 -0
- package/src/storage/objects/guard.ts +7 -3
- package/src/storage/objects/in-memory/conditional-reader.ts +72 -0
- package/src/storage/objects/in-memory/query.ts +4 -105
- package/src/storage/objects/in-memory/read-scope.ts +15 -14
- package/src/storage/objects/in-memory/read-source.ts +11 -1
- package/src/storage/objects/in-memory/scoped-reader.ts +243 -0
- package/src/storage/objects/in-memory/selected-reader.ts +6 -231
- package/src/storage/objects/in-memory/storage.ts +183 -1
- package/src/storage/objects/index.ts +9 -1
- package/src/storage/objects/read-scope.ts +191 -0
- package/src/storage/objects/types.ts +68 -1
- package/src/storage/ontology/in-memory/index.ts +3 -0
- package/src/storage/ontology/in-memory/materializations.ts +35 -0
- package/src/storage/ontology/in-memory/replacement-plans.ts +4 -0
- package/src/storage/ontology/in-memory/unique-values.ts +62 -0
- package/src/storage/ontology/index.ts +10 -0
- package/src/storage/ontology/materializations.ts +35 -1
- package/src/storage/ontology/provider-work.ts +76 -0
- package/src/storage/ontology/provider.ts +3 -0
- package/src/storage/ontology/unique-values.ts +56 -0
- package/src/storage/operation-scope.ts +9 -1
- package/src/storage/projection-runs/in-memory.ts +3 -35
- package/src/storage/types.ts +2 -0
- package/src/testing/agent-approval-storage-contract.ts +1117 -0
- package/src/testing/agent-memory-storage-contract.ts +400 -0
- package/src/testing/agent-storage-contract.ts +1188 -33
- package/src/testing/ai-cost-storage-contract.ts +31 -1
- package/src/testing/ai-limit-storage-contract.ts +9 -7
- package/src/testing/ai-model-call-groups-contract.ts +76 -0
- package/src/testing/ai-usage-storage-contract.ts +120 -13
- package/src/testing/artifact-storage-contract.ts +338 -4
- package/src/testing/auth-storage-contract.ts +550 -73
- package/src/testing/broker-contract.ts +28 -23
- package/src/testing/effective-storage-contract.ts +3 -8
- package/src/testing/execution-storage-contract.ts +53 -0
- package/src/testing/file-upload-session-storage-contract.ts +12 -24
- package/src/testing/index.ts +17 -4
- package/src/testing/lake-storage-contract.ts +22 -28
- package/src/testing/materializer-storage-contract.ts +36 -9
- package/src/testing/object-conditional-read-scope-contract.ts +634 -0
- package/src/testing/object-query-contract.ts +386 -186
- package/src/testing/ontology-storage-contract.ts +230 -21
- package/src/testing/projection-run-storage-contract.ts +8 -18
- package/src/testing/queues-contract.ts +39 -70
- package/src/testing/sandboxes-contract.ts +3 -14
- package/src/testing/share-grant-storage-contract.ts +13 -16
- package/src/testing/share-session-storage-contract.ts +4 -14
- package/src/testing/unique-values-contract.ts +907 -0
- package/src/testing/webhook-execution.ts +1 -1
- package/src/testing/webhook-run-storage-contract.ts +6 -9
- package/src/users/execution.ts +131 -0
- package/src/users/index.ts +2 -0
- package/src/workers/queue-worker.ts +1 -3
- package/src/workers/worker.ts +1 -3
- package/src/workflows/builders.ts +6 -0
- package/src/workflows/request.ts +46 -8
- package/src/workflows/types.ts +6 -2
- package/src/workflows/validation.ts +23 -9
- package/dist/chunk-29yx306f.js.map +0 -22
- package/dist/chunk-3jms7je7.js +0 -14
- package/dist/chunk-3jms7je7.js.map +0 -10
- package/dist/chunk-3qct2mdc.js +0 -297
- package/dist/chunk-3qct2mdc.js.map +0 -12
- package/dist/chunk-48qjhh6v.js.map +0 -13
- package/dist/chunk-4as3wt1c.js.map +0 -12
- package/dist/chunk-5948n82c.js.map +0 -10
- package/dist/chunk-5hx48dnn.js.map +0 -14
- package/dist/chunk-6rqgmkde.js.map +0 -29
- package/dist/chunk-6x0pqh32.js.map +0 -10
- package/dist/chunk-7n30ybym.js +0 -3
- package/dist/chunk-7n440zgt.js +0 -261
- package/dist/chunk-7n440zgt.js.map +0 -12
- package/dist/chunk-7q8t23v4.js +0 -467
- package/dist/chunk-7q8t23v4.js.map +0 -14
- package/dist/chunk-8frc8a4j.js.map +0 -20
- package/dist/chunk-918wwnaa.js.map +0 -68
- package/dist/chunk-91mg3nj9.js.map +0 -12
- package/dist/chunk-96yw3pwd.js.map +0 -10
- package/dist/chunk-9j4jw7as.js.map +0 -14
- package/dist/chunk-9k93ah50.js.map +0 -11
- package/dist/chunk-9kgkfg6v.js +0 -502
- package/dist/chunk-9kgkfg6v.js.map +0 -14
- package/dist/chunk-akzryx9h.js.map +0 -100
- package/dist/chunk-arns890k.js.map +0 -10
- package/dist/chunk-bk9svbcq.js.map +0 -49
- package/dist/chunk-c06hmxyy.js +0 -31
- package/dist/chunk-c06hmxyy.js.map +0 -10
- package/dist/chunk-c1rxbz5y.js.map +0 -12
- package/dist/chunk-cn0fwwhy.js.map +0 -19
- package/dist/chunk-dhcv7yxc.js.map +0 -11
- package/dist/chunk-dhdha526.js.map +0 -10
- package/dist/chunk-dvd2fp9q.js.map +0 -13
- package/dist/chunk-e6k4thh5.js.map +0 -19
- package/dist/chunk-ere85b8y.js.map +0 -15
- package/dist/chunk-g257jwnc.js.map +0 -12
- package/dist/chunk-hwksyjks.js.map +0 -11
- package/dist/chunk-k43ct2ke.js.map +0 -12
- package/dist/chunk-nn5xnx3s.js.map +0 -40
- package/dist/chunk-pbcbn83d.js.map +0 -14
- package/dist/chunk-pqajwytd.js +0 -68
- package/dist/chunk-pqajwytd.js.map +0 -11
- package/dist/chunk-qczk96d9.js.map +0 -11
- package/dist/chunk-rdghfsss.js +0 -39
- package/dist/chunk-rdghfsss.js.map +0 -10
- package/dist/chunk-rj69qcrd.js.map +0 -11
- package/dist/chunk-v4jbb3rs.js.map +0 -10
- package/dist/chunk-yxd3nnqt.js.map +0 -11
- package/dist/events/toStoredEvent.d.ts +0 -9
- package/dist/events/toStoredEvent.d.ts.map +0 -1
- package/dist/models/audio/file.d.ts +0 -9
- package/dist/models/audio/file.d.ts.map +0 -1
- package/src/events/toStoredEvent.ts +0 -33
- /package/dist/{chunk-mfs23znk.js.map → chunk-07kkp2e1.js.map} +0 -0
- /package/dist/{chunk-z58tm0hm.js.map → chunk-0phpbbvm.js.map} +0 -0
- /package/dist/{chunk-e17zdm62.js.map → chunk-1t6k1avb.js.map} +0 -0
- /package/dist/{chunk-kge7k6ey.js.map → chunk-2fn60nvs.js.map} +0 -0
- /package/dist/{chunk-y0c4e6ex.js.map → chunk-3gbefjg5.js.map} +0 -0
- /package/dist/{chunk-cy4mbddw.js.map → chunk-48jezz3j.js.map} +0 -0
- /package/dist/{chunk-twe4dx8p.js → chunk-5tfev0fv.js} +0 -0
- /package/dist/{chunk-twe4dx8p.js.map → chunk-5tfev0fv.js.map} +0 -0
- /package/dist/{chunk-447a5c0p.js.map → chunk-6n69k945.js.map} +0 -0
- /package/dist/{chunk-0bphap9y.js.map → chunk-6p0pastb.js.map} +0 -0
- /package/dist/{chunk-431pyp2c.js.map → chunk-6y0mkhex.js.map} +0 -0
- /package/dist/{chunk-s7jg7pmn.js.map → chunk-bab05bhg.js.map} +0 -0
- /package/dist/{chunk-q5e5tv4b.js.map → chunk-c844dkwd.js.map} +0 -0
- /package/dist/{chunk-cfj9dfbb.js.map → chunk-d2m879s4.js.map} +0 -0
- /package/dist/{chunk-q7gn29y3.js.map → chunk-dp0cdtj2.js.map} +0 -0
- /package/dist/{chunk-br3k6qbf.js.map → chunk-fm62y49k.js.map} +0 -0
- /package/dist/{chunk-vvxtn22d.js.map → chunk-g663fahq.js.map} +0 -0
- /package/dist/{chunk-rmakanzx.js.map → chunk-h33shhq6.js.map} +0 -0
- /package/dist/{chunk-d09e3rax.js.map → chunk-hwarjrgf.js.map} +0 -0
- /package/dist/{chunk-vf57cr4t.js.map → chunk-hyesv9dv.js.map} +0 -0
- /package/dist/{chunk-5vems3nx.js.map → chunk-m2nevja0.js.map} +0 -0
- /package/dist/{chunk-x9v4cx1d.js.map → chunk-m36fw8ft.js.map} +0 -0
- /package/dist/{chunk-a40ad1ft.js.map → chunk-mbsbxarb.js.map} +0 -0
- /package/dist/{chunk-6aawea28.js.map → chunk-n8q5j6y5.js.map} +0 -0
- /package/dist/{chunk-d7dnxdep.js.map → chunk-n9zpx9c6.js.map} +0 -0
- /package/dist/{chunk-xvsc5m8n.js.map → chunk-npcr0228.js.map} +0 -0
- /package/dist/{chunk-y5tah2kf.js.map → chunk-q4pmvkg0.js.map} +0 -0
- /package/dist/{chunk-d5rjr8c0.js.map → chunk-vabga7fk.js.map} +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/auth/access-tokens.ts", "../src/auth/client-address.ts", "../src/auth/csrf.ts", "../src/auth/runtime.ts", "../src/security/every.ts", "../src/actions/errors.ts", "../src/actions/validation.ts", "../src/shares/errors.ts", "../src/shares/builders.ts", "../src/security/project.ts", "../src/security/grants.ts", "../src/objects/query/current-user.ts", "../src/objects/vectors/profile.ts", "../src/objects/vectors/query.ts", "../src/objects/query/reranking-limits.ts", "../src/objects/query/validate.ts", "../src/security/view-conditions.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/users/execution.ts", "../src/auth/member-events.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
|
+
"// The server resolves each request's client address once, at the socket, from the peer address\n// and the forwarding headers its trusted proxies wrote. Everything else reads it from here and\n// never parses forwarding headers itself: a client can write any value into them.\nconst clientAddresses = new WeakMap<Request, string>()\n\nexport function setRequestClientAddress(request: Request, address: string): void {\n clientAddresses.set(request, address)\n}\n\nexport function getRequestClientAddress(request: Request): string | undefined {\n return clientAddresses.get(request)\n}\n",
|
|
7
|
+
"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 }\n): boolean {\n if (isCsrfExemptMethod(request.method)) {\n return true\n }\n\n return verifyCsrfToken(request, {\n cookieName: options.cookieName,\n token: request.headers.get(CSRF_HEADER_NAME),\n })\n}\n\n/** Match a submitted CSRF token (header or form field) against the request's CSRF cookie. */\nexport function verifyCsrfToken(\n request: Request,\n options: { readonly cookieName: string; readonly token: string | null }\n): boolean {\n const cookieValue = getCookie(request, options.cookieName)\n if (!cookieValue || !options.token) {\n return false\n }\n\n return safeEqual(cookieValue, options.token)\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",
|
|
8
|
+
"import { randomUUID } from \"node:crypto\"\nimport { type AuthorizationContext, resolveAuthorizationContext } from \"../authorization\"\nimport type { DomainEventLog } from \"../events/service\"\nimport type { EventDraft } from \"../events/types\"\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 CreateAuthSessionInput,\n type GroupMembershipRecord,\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 { toUserProfile } from \"../users/execution\"\nimport {\n createAccessTokenCredential,\n getBearerAccessTokenValue,\n hashAccessTokenSecret,\n parseAccessTokenValue,\n} from \"./access-tokens\"\nimport { getRequestClientAddress } from \"./client-address\"\nimport { getCookie, type ResolvedAuthCookieOptions } from \"./cookies\"\nimport { AuthRuntimeError } from \"./errors\"\nimport {\n invitedEvents,\n profileUpdatedEvents,\n signInEvents,\n statusChangedEvents,\n} from \"./member-events\"\nimport { normalizeProfileChanges, signInDisplayName } from \"./profile\"\nimport { SessionCache } from \"./session-cache\"\nimport {\n type BearerSessionTokens,\n createBearerSessionTokens,\n hashSessionSecret,\n parseBearerSessionToken,\n parseSessionCookieValue,\n SESSION_ACCESS_TOKEN_PREFIX,\n SESSION_REFRESH_TOKEN_PREFIX,\n} 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 InvitationDestination,\n InvitationGroupOption,\n InvitationRecipientStatus,\n InviteDeliveryResult,\n InviteDeliveryStatus,\n InviteUserInput,\n InviteUserResult,\n ListInvitationsInput,\n ListInvitationsResult,\n ListMembersInput,\n ListMembersResult,\n ListPersonalAccessTokensResult,\n ListServiceAccountAccessTokensInput,\n ListServiceAccountAccessTokensResult,\n ListServiceAccountsResult,\n MagicLinkCallbackInput,\n MagicLinkCallbackResult,\n MemberSummary,\n MembershipCapabilities,\n OidcCallbackInput,\n OidcCallbackResult,\n OwnProfile,\n ProfileField,\n ReactivateMemberInput,\n ReactivateMemberResult,\n ResolvedAuthConfig,\n RevokeAccessTokenResult,\n RevokeInvitationInput,\n RevokeInvitationResult,\n RevokePersonalAccessTokenInput,\n RevokeServiceAccountAccessTokenInput,\n RevokeServiceAccountAccessTokenResult,\n SixbAuthConfig,\n SuspendMemberInput,\n SuspendMemberResult,\n UnauthenticatedAuthSession,\n UpdateMemberGroupsInput,\n UpdateMemberGroupsResult,\n UpdateOwnProfileInput,\n} from \"./types\"\nimport {\n assertNonEmpty,\n isInvitationDeliveryAuthStrategy,\n isMagicLinkAuthStrategy,\n isOidcAuthStrategy,\n normalizePagination,\n resolveAuthConfig,\n resolveInvitationExpiresAt,\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\n// A native client's access token is sent on every request, so a leaked one must stop working soon.\nconst BEARER_ACCESS_TOKEN_TTL_MS = 15 * 60_000\n// A replaced refresh token still rotates this long after its replacement, so a client whose refresh\n// response was lost can retry. Later, it means a copy is in use and the session is revoked.\nconst REFRESH_REUSE_GRACE_MS = 60_000\n\nconst PROFILE_FIELDS: readonly ProfileField[] = [\"displayName\", \"avatarUrl\"]\n\nexport interface AuthRuntimeOptions {\n readonly projectId: string\n readonly storage: Storage\n readonly security: SecurityDefinitionCatalog\n readonly config?: SixbAuthConfig\n /** Where member events go: joined, suspended, reactivated, invited, profile updated. */\n readonly events: DomainEventLog\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 private readonly events: DomainEventLog\n\n constructor(options: AuthRuntimeOptions) {\n this.projectId = options.projectId\n this.storage = options.storage\n this.security = options.security\n this.events = options.events\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(): ResolvedAuthCookieOptions {\n return this.config.cookies\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: \"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 if (options.credentialSource === \"any\") {\n const tokenValue = getBearerAccessTokenValue(request)\n if (tokenValue?.startsWith(SESSION_ACCESS_TOKEN_PREFIX)) {\n return this.resolveBearerSession(tokenValue)\n }\n if (tokenValue) {\n return this.resolveAccessTokenSession(request, tokenValue)\n }\n\n // An Authorization header that is not a usable token never falls back to the cookie.\n if (request.headers.get(\"authorization\")) {\n return { authenticated: false, reason: \"invalid_access_token\" }\n }\n }\n\n return this.resolveCookieSession(request, options.sessionActivity)\n }\n\n private async resolveCookieSession(\n request: Request,\n activity: AuthSessionResolutionOptions[\"sessionActivity\"]\n ): Promise<AuthSessionResult> {\n const cookieOptions = this.getCookieOptions()\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 transport: \"cookie\",\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 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 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 if (!sessionRenewed) {\n await this.touchSessionLastSeen(storage, session, now)\n }\n const result = await this.authenticateSession(storage, session, tokenHash, now)\n return result.authenticated && sessionRenewed ? { ...result, sessionRenewed: true } : result\n }\n\n private async resolveBearerSession(tokenValue: string): Promise<AuthSessionResult> {\n const parts = parseBearerSessionToken(SESSION_ACCESS_TOKEN_PREFIX, tokenValue)\n if (!parts) {\n return { authenticated: false, reason: \"invalid_access_token\" }\n }\n\n const tokenHash = hashSessionSecret(parts.sessionSecret)\n const now = new Date()\n const cached = this.sessionCache?.get({\n sessionId: parts.sessionId,\n tokenHash,\n transport: \"bearer\",\n nowMs: now.getTime(),\n })\n if (cached) {\n return cached\n }\n\n const storage = this.requireAuthStorage()\n const session = await storage.sessions.findValidByAccessTokenHash({\n projectId: this.projectId,\n id: parts.sessionId,\n tokenHash,\n now,\n })\n if (!session) {\n return { authenticated: false, reason: \"invalid_access_token\" }\n }\n\n await this.touchSessionLastSeen(storage, session, now)\n return this.authenticateSession(storage, session, tokenHash, now)\n }\n\n /** Resolve a live session's user and groups, the same way for cookies and bearer tokens. */\n private async authenticateSession(\n storage: AuthStorage,\n session: SessionRecord,\n tokenHash: string,\n now: Date\n ): Promise<AuthSessionResult> {\n const member = await this.loadActiveUser(storage, session.userId)\n if (!member.authenticated) {\n return member\n }\n\n const result: AuthenticatedAuthSession = {\n authenticated: true,\n credentialSource: \"session\",\n principal: { type: \"user\", id: member.user.id },\n user: member.user,\n session,\n groupIds: member.groupIds,\n }\n this.sessionCache?.set({\n sessionId: session.id,\n tokenHash,\n session: result,\n nowMs: now.getTime(),\n sessionExpiresAtMs: session.expiresAt.getTime(),\n sessionAbsoluteExpiresAtMs: session.absoluteExpiresAt?.getTime(),\n })\n return result\n }\n\n /**\n * The session a native client starts when the user approves it, and its first tokens. The caller\n * stores the session in the same transaction that consumes the approval.\n */\n prepareBearerSession(input: {\n readonly userId: string\n readonly clientName: string\n readonly now: Date\n }): {\n readonly session: CreateAuthSessionInput & {\n readonly bearer: NonNullable<CreateAuthSessionInput[\"bearer\"]>\n }\n readonly tokens: BearerSessionTokens\n } {\n const sessionId = `ses_${randomUUID()}`\n const tokens = createBearerSessionTokens(sessionId)\n return {\n tokens,\n session: {\n id: sessionId,\n projectId: this.projectId,\n userId: input.userId,\n strategyId: \"device\",\n tokenHash: tokens.tokenHash,\n createdAt: input.now,\n ...this.createSessionDeadlines(input.now),\n bearer: {\n clientName: input.clientName,\n accessExpiresAt: new Date(input.now.getTime() + BEARER_ACCESS_TOKEN_TTL_MS),\n refreshTokenHash: tokens.refreshTokenHash,\n },\n },\n }\n }\n\n /**\n * Trade a native client's refresh token for new tokens. Returns null when the token is not\n * accepted; a replaced token presented after the grace window also revokes its session.\n */\n async refreshSession(\n refreshToken: string\n ): Promise<{ readonly tokens: BearerSessionTokens; readonly session: SessionRecord } | null> {\n const parts = parseBearerSessionToken(SESSION_REFRESH_TOKEN_PREFIX, refreshToken)\n if (!parts || !this.isEnabled()) {\n return null\n }\n\n const now = new Date()\n const tokens = createBearerSessionTokens(parts.sessionId)\n const result = await this.requireAuthStorage().sessions.rotateRefreshToken({\n projectId: this.projectId,\n id: parts.sessionId,\n refreshTokenHash: hashSessionSecret(parts.sessionSecret),\n now,\n reuseGraceMs: REFRESH_REUSE_GRACE_MS,\n next: {\n tokenHash: tokens.tokenHash,\n accessExpiresAt: new Date(now.getTime() + BEARER_ACCESS_TOKEN_TTL_MS),\n refreshTokenHash: tokens.refreshTokenHash,\n expiresAt: new Date(now.getTime() + this.config.session.idleTimeoutMs),\n },\n })\n this.sessionCache?.invalidate(parts.sessionId)\n return result.status === \"rotated\" ? { tokens, session: result.session } : null\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.subject.type === \"user\") {\n const member = await this.loadActiveUser(storage, accessToken.subject.id)\n if (!member.authenticated) {\n return member\n }\n\n return {\n authenticated: true,\n credentialSource: \"accessToken\",\n principal: { type: \"user\", id: member.user.id },\n user: member.user,\n accessToken,\n groupIds: constrainTokenGroupIds(member.groupIds, accessToken),\n }\n }\n\n const serviceAccount = await storage.serviceAccounts.getById({\n projectId: this.projectId,\n id: accessToken.subject.id,\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 /** Resolve a user and their current groups the same way for every credential. */\n private async loadActiveUser(\n storage: AuthStorage,\n userId: string\n ): Promise<\n | UnauthenticatedAuthSession\n | { readonly authenticated: true; readonly user: UserRecord; readonly groupIds: string[] }\n > {\n const user = await storage.users.getById({ projectId: this.projectId, id: userId })\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,\n })\n return {\n authenticated: true,\n user,\n groupIds: memberships.map((membership) => membership.groupId),\n }\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: getRequestClientAddress(request),\n })\n } catch {\n // Touch is non-critical; ignore failures so auth still succeeds.\n }\n }\n\n /**\n * Finish a magic-link sign-in: consume the link and start the session the server minted. Every\n * sign-in goes through the runtime, so what follows one is decided here and not in each route.\n * A name that breaks the profile rules is dropped: it never makes the sign-in fail.\n */\n async completeMagicLinkSignIn(\n input: Pick<MagicLinkCallbackInput, \"magicLinkId\" | \"token\" | \"session\" | \"displayName\">\n ): Promise<MagicLinkCallbackResult> {\n const strategy = this.getStrategy()\n if (!isMagicLinkAuthStrategy(strategy)) {\n throw new AuthRuntimeError(\n \"invalid_auth_config\",\n \"[Sixb] The active auth strategy does not support magic-link sign-in.\"\n )\n }\n\n const result = await strategy.completeMagicLinkSignIn({\n projectId: this.projectId,\n authStorage: this.requireAuthStorage(),\n magicLinkId: input.magicLinkId,\n token: input.token,\n session: input.session,\n displayName: signInDisplayName(input.displayName),\n })\n\n await this.emitMemberEvents(signInEvents(result))\n\n return result\n }\n\n /** Finish an OIDC sign-in from the provider's callback and start the session the server minted. */\n async completeOidcSignIn(\n input: Pick<OidcCallbackInput, \"requestUrl\" | \"requestOrigin\" | \"session\">\n ): Promise<OidcCallbackResult> {\n const strategy = this.getStrategy()\n if (!isOidcAuthStrategy(strategy)) {\n throw new AuthRuntimeError(\n \"invalid_auth_config\",\n \"[Sixb] The active auth strategy does not support OIDC sign-in.\"\n )\n }\n\n const result = await strategy.completeOidcSignIn({\n projectId: this.projectId,\n authStorage: this.requireAuthStorage(),\n requestUrl: input.requestUrl,\n requestOrigin: input.requestOrigin,\n session: input.session,\n })\n\n // The provider may have changed the person's name, picture or directory groups, which their\n // other sessions hold in the cache.\n this.sessionCache?.invalidateUser(result.user.id)\n\n await this.emitMemberEvents(signInEvents(result))\n\n return result\n }\n\n /**\n * Resolve a caller's authorization context. Grants resolve eagerly\n * (`groups -> roles -> grants`, subtype-expanded), so checks against it are synchronous.\n */\n contextFromSession(session: AuthenticatedRequestAuthSession): AuthorizationContext {\n return resolveAuthorizationContext({\n principal: session.principal,\n sessionId: callerSessionId(session),\n groupIds: session.groupIds,\n roles: this.security.listResolvedRoles(),\n })\n }\n\n async listPersonalAccessTokens(\n caller: AuthenticatedUserRequestSession\n ): Promise<ListPersonalAccessTokensResult> {\n const storage = this.requireAuthStorage()\n const result = await storage.accessTokens.list({\n projectId: this.projectId,\n kind: \"personal\",\n subject: { type: \"user\", id: caller.user.id },\n includeRevoked: true,\n order: \"desc\",\n limit: 100,\n })\n\n return { accessTokens: result.accessTokens }\n }\n\n async createPersonalAccessToken(\n caller: AuthenticatedUserRequestSession,\n input: CreatePersonalAccessTokenInput\n ): Promise<CreateAccessTokenResult> {\n assertSessionCaller(caller)\n const storage = this.requireAuthStorage()\n // A personal token can only carry groups the caller currently belongs to.\n const groupIds = constrainRequestedGroupIds(input.groupIds, caller.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 subject: { type: \"user\", id: caller.user.id },\n tokenHash: credential.tokenHash,\n groupIds,\n createdByPrincipal: caller.principal,\n createdBySessionId: callerSessionId(caller),\n createdAt: new Date(),\n expiresAt: input.expiresAt,\n })\n\n return { accessToken, tokenValue: credential.tokenValue }\n }\n\n async revokePersonalAccessToken(\n caller: AuthenticatedUserRequestSession,\n input: RevokePersonalAccessTokenInput\n ): Promise<RevokeAccessTokenResult> {\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.subject.type !== \"user\" ||\n token.subject.id !== caller.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 caller: AuthenticatedUserRequestSession\n ): Promise<ListServiceAccountsResult> {\n const storage = this.requireAuthStorage()\n const scope = this.resolveMembershipPolicyScopeForUser(caller.groupIds)\n if (scope.operations.serviceAccounts.policyIds.length === 0) {\n return { serviceAccounts: [] }\n }\n\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 its membership policies cover, so\n // listing never leaks the groups of accounts outside its scope.\n return {\n serviceAccounts: withGroups.filter(({ groupIds }) =>\n canPerformMembershipOperation(scope, \"serviceAccounts\", groupIds)\n ),\n }\n }\n\n async createServiceAccount(\n caller: AuthenticatedUserRequestSession,\n input: CreateServiceAccountInput\n ): Promise<CreateServiceAccountResult> {\n const storage = this.requireAuthStorage()\n // A caller can only place a service account in groups its `serviceAccounts` policies cover.\n const groupIds = normalizeRequestedGroupIds(input.groupIds) ?? []\n this.assertCanManageServiceAccountGroups(caller.groupIds, groupIds)\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: caller.principal,\n createdBySessionId: callerSessionId(caller),\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 caller: AuthenticatedUserRequestSession,\n input: DisableServiceAccountInput\n ): Promise<DisableServiceAccountResult> {\n const storage = this.requireAuthStorage()\n const { serviceAccount, groupIds } = await this.requireManageableServiceAccount(\n storage,\n caller.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 caller: AuthenticatedUserRequestSession,\n input: ListServiceAccountAccessTokensInput\n ): Promise<ListServiceAccountAccessTokensResult> {\n const storage = this.requireAuthStorage()\n const { serviceAccount } = await this.requireManageableServiceAccount(\n storage,\n caller.groupIds,\n input.serviceAccountId\n )\n const result = await storage.accessTokens.list({\n projectId: this.projectId,\n kind: \"serviceAccount\",\n subject: { type: \"serviceAccount\", id: 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 caller: AuthenticatedUserRequestSession,\n input: CreateServiceAccountAccessTokenInput\n ): Promise<CreateServiceAccountAccessTokenResult> {\n assertSessionCaller(caller)\n const storage = this.requireAuthStorage()\n const { serviceAccount, groupIds: serviceAccountGroupIds } =\n await this.requireManageableServiceAccount(storage, caller.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 within the caller's\n // `serviceAccounts` scope, so the token never reaches past that scope.\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 subject: { type: \"serviceAccount\", id: serviceAccount.id },\n tokenHash: credential.tokenHash,\n groupIds,\n createdByPrincipal: caller.principal,\n createdBySessionId: callerSessionId(caller),\n createdAt: new Date(),\n expiresAt: input.expiresAt,\n })\n\n return { accessToken, tokenValue: credential.tokenValue, serviceAccount }\n }\n\n async revokeServiceAccountAccessToken(\n caller: AuthenticatedUserRequestSession,\n input: RevokeServiceAccountAccessTokenInput\n ): Promise<RevokeServiceAccountAccessTokenResult> {\n const storage = this.requireAuthStorage()\n const { serviceAccount } = await this.requireManageableServiceAccount(\n storage,\n caller.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.subject.type !== \"serviceAccount\" ||\n token.subject.id !== 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 needs a membership policy with the `serviceAccounts` operation whose scope covers every\n * group the account is in (\"you can manage what you could have created\"). This confines token\n * minting, disabling, and revocation to the groups the project's policies hand out. Missing and\n * out-of-scope accounts raise the same error so callers cannot probe which 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 scope = this.resolveMembershipPolicyScopeForUser(callerGroupIds)\n if (scope.operations.serviceAccounts.policyIds.length === 0) {\n throw missingServiceAccountsPolicyError()\n }\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 || !canPerformMembershipOperation(scope, \"serviceAccounts\", 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 caller: AuthenticatedUserRequestSession\n ): Promise<GetInvitationOptionsResult> {\n const scope = this.resolveMembershipPolicyScopeForUser(caller.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 caller: AuthenticatedUserRequestSession\n ): Promise<GetMembershipOptionsResult> {\n const scope = this.resolveMembershipPolicyScopeForUser(caller.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 serviceAccountGroups: this.scopedGroupOptions(scope.operations.serviceAccounts.groupIds),\n capabilities: membershipCapabilities(scope).holds,\n }\n }\n\n async listMembers(\n caller: AuthenticatedUserRequestSession,\n input: ListMembersInput = {}\n ): Promise<ListMembersResult> {\n const storage = this.requireAuthStorage()\n const scope = this.resolveMembershipPolicyScopeForUser(caller.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, managedGroupIds } = memberGroups(\n await storage.groupMemberships.listForUser({ projectId: this.projectId, userId: user.id })\n )\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 === caller.user.id\n members.push({\n user,\n groupIds,\n managedGroupIds,\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 caller: AuthenticatedUserRequestSession,\n input: UpdateMemberGroupsInput\n ): Promise<UpdateMemberGroupsResult> {\n const storage = this.requireAuthStorage()\n const scope = this.resolveMembershipPolicyScopeForUser(caller.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 {\n user,\n groupIds: currentGroupIds,\n managedGroupIds: currentManagedGroupIds,\n } = await this.requireManageableMember(storage, scope, \"assignGroups\", userId)\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 // The identity provider would restore these at the user's next sign-in.\n const managedRemovals = removals.filter((groupId) => currentManagedGroupIds.includes(groupId))\n if (managedRemovals.length > 0) {\n throw new AuthRuntimeError(\n \"invalid_auth_input\",\n `[Sixb] Group(s) ${managedRemovals.join(\", \")} are managed by the identity provider. Change them there; they sync at the user's next sign-in.`\n )\n }\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 === caller.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.sessionCache?.invalidateUser(user.id)\n\n const { groupIds, managedGroupIds } = memberGroups(\n await storage.groupMemberships.listForUser({ projectId: this.projectId, userId: user.id })\n )\n\n return { user, groupIds, managedGroupIds }\n }\n\n async suspendMember(\n caller: AuthenticatedUserRequestSession,\n input: SuspendMemberInput\n ): Promise<SuspendMemberResult> {\n const storage = this.requireAuthStorage()\n const scope = this.resolveMembershipPolicyScopeForUser(caller.groupIds)\n const userId = assertNonEmpty(input.userId, \"User id\")\n const { user, groupIds, managedGroupIds } = await this.requireManageableMember(\n storage,\n scope,\n \"suspend\",\n userId\n )\n\n if (user.id === caller.user.id) {\n throw new AuthRuntimeError(\n \"authorization_denied\",\n \"[Sixb] The current user cannot suspend themselves.\"\n )\n }\n\n const { user: suspended, previousUser } = 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.sessionCache?.invalidateUser(user.id)\n\n await this.emitMemberEvents(statusChangedEvents(caller, previousUser, suspended))\n\n return { user: suspended, groupIds, managedGroupIds }\n }\n\n async reactivateMember(\n caller: AuthenticatedUserRequestSession,\n input: ReactivateMemberInput\n ): Promise<ReactivateMemberResult> {\n const storage = this.requireAuthStorage()\n const scope = this.resolveMembershipPolicyScopeForUser(caller.groupIds)\n const userId = assertNonEmpty(input.userId, \"User id\")\n const { user, groupIds, managedGroupIds } = await this.requireManageableMember(\n storage,\n scope,\n \"suspend\",\n userId\n )\n\n // Reactivation restores access but not sessions; the user signs in again.\n const { user: reactivated, previousUser } = await storage.users.updateStatus({\n projectId: this.projectId,\n id: user.id,\n status: \"active\",\n updatedAt: new Date(),\n })\n\n await this.emitMemberEvents(statusChangedEvents(caller, previousUser, reactivated))\n\n return { user: reactivated, groupIds, managedGroupIds }\n }\n\n /** The caller's own profile, and which of its fields their identity provider manages. */\n async getProfile(caller: AuthenticatedUserRequestSession): Promise<OwnProfile> {\n const storage = this.requireAuthStorage()\n const user = await storage.users.getById({ projectId: this.projectId, id: caller.user.id })\n if (!user) {\n throw new AuthStorageError(\n \"missing_user\",\n `[Sixb] User '${caller.user.id}' not found for project '${this.projectId}'.`\n )\n }\n\n return {\n profile: toUserProfile(user),\n managedFields: await this.managedProfileFields(storage, user.id),\n }\n }\n\n /**\n * Change the caller's own name or picture. A field their identity provider manages is refused,\n * because the next sign-in would overwrite it.\n */\n async updateProfile(\n caller: AuthenticatedUserRequestSession,\n input: UpdateOwnProfileInput\n ): Promise<OwnProfile> {\n const changes = normalizeProfileChanges(input)\n const storage = this.requireAuthStorage()\n const managedFields = await this.managedProfileFields(storage, caller.user.id)\n\n const managedChanges = managedFields.filter((field) => changes[field] !== undefined)\n if (managedChanges.length > 0) {\n throw new AuthRuntimeError(\n \"authorization_denied\",\n `[Sixb] Your identity provider manages ${managedChanges.join(\" and \")}. ` +\n `Change ${managedChanges.length > 1 ? \"them\" : \"it\"} there.`\n )\n }\n\n const { user, previousUser } = await storage.users.updateProfile({\n projectId: this.projectId,\n id: caller.user.id,\n ...changes,\n updatedAt: new Date(),\n })\n\n // Every session of this person caches their profile; drop them so all show the change.\n const changed =\n user.displayName !== previousUser.displayName || user.avatarUrl !== previousUser.avatarUrl\n if (changed) {\n this.sessionCache?.invalidateUser(user.id)\n }\n\n await this.emitMemberEvents(profileUpdatedEvents(caller, previousUser, user))\n\n return { profile: toUserProfile(user), managedFields }\n }\n\n // The fields the active strategy's provider sets at sign-in, through any of the person's\n // identities with it. Identities from a strategy the project no longer uses manage nothing.\n private async managedProfileFields(\n storage: AuthStorage,\n userId: string\n ): Promise<readonly ProfileField[]> {\n const strategy = this.getStrategy()\n if (!strategy?.providerProfileFields) {\n return []\n }\n\n const identities = await storage.identities.listForUser({ projectId: this.projectId, userId })\n const managed = new Set<ProfileField>()\n for (const identity of identities) {\n if (identity.strategyId !== strategy.id) {\n continue\n }\n for (const field of strategy.providerProfileFields(identity)) {\n managed.add(field)\n }\n }\n\n return PROFILE_FIELDS.filter((field) => managed.has(field))\n }\n\n /** The caller's active sessions, most recently active first. */\n async listSessions(caller: AuthenticatedUserRequestSession): Promise<readonly SessionRecord[]> {\n return this.requireAuthStorage().sessions.listActiveByUserId({\n projectId: this.projectId,\n userId: caller.user.id,\n now: new Date(),\n })\n }\n\n /**\n * End one of the caller's own sessions. Returns false for a missing session or one that belongs\n * to another user, so a caller cannot probe other accounts.\n */\n async revokeSession(\n caller: AuthenticatedUserRequestSession,\n sessionId: string\n ): Promise<boolean> {\n const storage = this.requireAuthStorage()\n const session = await storage.sessions.getById({ projectId: this.projectId, id: sessionId })\n if (!session || session.userId !== caller.user.id) {\n return false\n }\n\n await storage.sessions.revoke({\n projectId: this.projectId,\n id: sessionId,\n revokedAt: new Date(),\n })\n this.sessionCache?.invalidate(sessionId)\n return true\n }\n\n /** End every active session of the caller. Returns how many ended. */\n async revokeAllSessions(caller: AuthenticatedUserRequestSession): Promise<number> {\n const revoked = await this.requireAuthStorage().sessions.revokeActiveForUser({\n projectId: this.projectId,\n userId: caller.user.id,\n revokedAt: new Date(),\n })\n for (const session of revoked) {\n this.sessionCache?.invalidate(session.id)\n }\n return revoked.length\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<{\n readonly user: UserRecord\n readonly groupIds: readonly string[]\n readonly managedGroupIds: readonly string[]\n }> {\n const user = await storage.users.getById({ projectId: this.projectId, id: userId })\n const { groupIds, managedGroupIds } = memberGroups(\n user ? await storage.groupMemberships.listForUser({ projectId: this.projectId, userId }) : []\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, managedGroupIds }\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 caller: AuthenticatedUserRequestSession,\n input: InviteUserInput,\n destination: InvitationDestination\n ): Promise<InviteUserResult> {\n const authStorage = this.requireAuthStorage()\n const now = new Date()\n const groupIds = this.resolveInviteGroupIds(input)\n this.assertCanManageInvitationGroups(caller.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\n const invitation = await authStorage.invitations.createOrUpdateActive({\n id: `inv_${randomUUID()}`,\n projectId: this.projectId,\n email: input.email,\n groupIds,\n createdByPrincipal: caller.principal,\n createdBySessionId: callerSessionId(caller),\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 returnTo: destination.returnTo,\n requestOrigin: destination.requestOrigin,\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 !== \"sent\" && delivery.status !== \"not_supported\") {\n await this.revokeInvitationAfterDeliveryFailure(authStorage, invitation, now)\n throw this.createInvitationDeliveryError(delivery.status)\n }\n\n await this.emitMemberEvents(invitedEvents(caller, invitation))\n\n return { invitation, delivery }\n }\n\n async listInvitations(\n caller: AuthenticatedUserRequestSession,\n input: ListInvitationsInput = {}\n ): Promise<ListInvitationsResult> {\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(caller.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 caller: AuthenticatedUserRequestSession,\n input: RevokeInvitationInput\n ): Promise<RevokeInvitationResult> {\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(caller.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 /**\n * Member events follow the auth write that caused them, which has already committed. Auth\n * storage keeps no outbox, so an event the broker refuses is reported through `onError` and lost:\n * delivery is at most once.\n */\n private async emitMemberEvents(events: readonly EventDraft[]): Promise<void> {\n if (events.length === 0) return\n\n await this.events.emit({ events }, { source: \"Sixb\" })\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 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 assertCanManageServiceAccountGroups(\n callerGroupIds: readonly string[],\n groupIds: readonly string[]\n ): void {\n const scope = this.resolveMembershipPolicyScopeForUser(callerGroupIds)\n\n if (canPerformMembershipOperation(scope, \"serviceAccounts\", groupIds)) {\n return\n }\n\n if (scope.operations.serviceAccounts.policyIds.length === 0) {\n throw missingServiceAccountsPolicyError()\n }\n\n const missing = missingMembershipGroupIds(scope, \"serviceAccounts\", groupIds)\n throw new AuthRuntimeError(\n \"authorization_denied\",\n `[Sixb] The current user is not allowed to place service accounts in group(s): ${missing.join(\", \")}.`\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 memberGroups(memberships: readonly GroupMembershipRecord[]): {\n readonly groupIds: readonly string[]\n readonly managedGroupIds: readonly string[]\n} {\n return {\n groupIds: memberships.map((membership) => membership.groupId),\n managedGroupIds: memberships\n .filter((membership) => membership.source === \"directory\")\n .map((membership) => membership.groupId),\n }\n}\n\n/** The interactive session a caller authenticated with, when it used one. */\nfunction callerSessionId(caller: AuthenticatedRequestAuthSession): string | undefined {\n return caller.credentialSource === \"session\" ? caller.session.id : undefined\n}\n\n// Access tokens are created only by a signed-in person, never by another access token. A token\n// minting one could hand out more groups or a later expiry than it carries, and what it minted\n// would outlive its own revocation.\nfunction assertSessionCaller(caller: AuthenticatedUserRequestSession): void {\n if (caller.credentialSource !== \"session\") {\n throw new AuthRuntimeError(\n \"authorization_denied\",\n \"[Sixb] Access tokens can only be created from a signed-in session, not with another access token.\"\n )\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\nfunction missingServiceAccountsPolicyError(): AuthRuntimeError {\n return new AuthRuntimeError(\n \"authorization_denied\",\n \"[Sixb] Managing service accounts needs a membership policy with the 'serviceAccounts' operation.\"\n )\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 serviceAccounts: scope.operations.serviceAccounts.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",
|
|
9
|
+
"/**\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 client builders such as `logs.actions()`.\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 { ShareDefinition } from \"../shares\"\nimport type { SyncDefinition } from \"../syncs\"\nimport type { WorkflowDefinition } from \"../workflows/types\"\nimport { SecurityValidationError } from \"./errors\"\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 \"connector\",\n \"share\",\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 connector: ConnectorDefinition\n share: ShareDefinition\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 connector: (): BreadthSelector<\"connector\"> => all(\"connector\"),\n share: (): BreadthSelector<\"share\"> => all(\"share\"),\n}\n",
|
|
10
|
+
"export class ActionDefinitionError extends Error {\n readonly name = \"ActionDefinitionError\"\n}\n\nexport function missingActionMutationMessage(actionId: string): string {\n return `Action \"${actionId}\" must declare .writeback(...) or .edits(...).`\n}\n\nexport function effectsWithoutEditsMessage(actionId: string): string {\n return `Action \"${actionId}\" cannot declare .effects(...) without .edits(...).`\n}\n",
|
|
11
|
+
"import type { ValueType } from \"../ontology\"\nimport { OntologyValidationError } from \"../ontology/errors\"\nimport type { ObjectTypeWithPropertyTokens } from \"../ontology/tokens\"\nimport { assertValidFileRefs } from \"../ontology/validation\"\nimport { coerceParamsToTyped, normalizeParams } from \"../shared/params/validation\"\nimport type { ActionRunParams } from \"../storage/action-runs\"\nimport { ActionDefinitionError } from \"./errors\"\nimport type {\n ActionDefinition,\n ActionParamsConfig,\n ActionSubject,\n GlobalActionDefinition,\n ObjectActionDefinition,\n} from \"./types\"\n\ninterface ActionValidationRuntime {\n readonly ontology: {\n getValueTypesById(): ReadonlyMap<string, ValueType>\n resolveObjectType(objectTypeId: string): ObjectTypeWithPropertyTokens\n }\n readonly actionRegistry: {\n listForType(objectType: ObjectTypeWithPropertyTokens): readonly ObjectActionDefinition[]\n }\n}\n\nexport function assertNonEmpty(value: string, field: string): void {\n if (!value.trim()) {\n throw new ActionDefinitionError(`Action ${field} must not be empty.`)\n }\n}\n\nexport function isActionDefinition(value: unknown): value is ActionDefinition {\n const binding = (value as { binding?: { kind?: unknown } } | null)?.binding\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as { kind?: unknown }).kind === \"action\" &&\n (binding?.kind === \"global\" || binding?.kind === \"object\")\n )\n}\n\nexport function isGlobalActionDefinition(value: ActionDefinition): value is GlobalActionDefinition {\n return value.binding.kind === \"global\"\n}\n\nexport function isObjectActionDefinition(value: ActionDefinition): value is ObjectActionDefinition {\n return value.binding.kind === \"object\"\n}\n\nexport function normalizeActionParams(\n runtime: Pick<ActionValidationRuntime, \"ontology\">,\n paramsConfig: ActionParamsConfig,\n params: Record<string, unknown>,\n pathPrefix: string\n): ActionRunParams {\n const normalized = normalizeParams(runtime.ontology.getValueTypesById(), paramsConfig, params, {\n kind: \"action\",\n id: pathPrefix,\n })\n assertValidFileRefs(normalized, pathPrefix)\n return normalized\n}\n\n/**\n * Re-hydrate stored action params for the handler-facing surface. Params are\n * normalized to JSON (e.g. `date`/`timestamp` -> ISO string) for storage; action\n * handler types promise `Date` for those, so this converts them back before the\n * handler runs. `objectRef` params pass through unchanged.\n */\nexport function coerceActionParamsToTyped(\n paramsConfig: ActionParamsConfig,\n params: Record<string, unknown>,\n valueTypesById: ReadonlyMap<string, ValueType>\n): Record<string, unknown> {\n return coerceParamsToTyped(paramsConfig, params, valueTypesById)\n}\n\nexport function validateActionSubject(action: ActionDefinition, subject: ActionSubject): void {\n if (isGlobalActionDefinition(action) && subject.kind !== \"none\") {\n throw new OntologyValidationError(`Action '${action.id}' does not accept an object subject.`)\n }\n}\n\nexport function resolveObjectActionSubject(params: {\n readonly runtime: ActionValidationRuntime\n readonly action: ObjectActionDefinition\n readonly subject: ActionSubject\n}): ObjectTypeWithPropertyTokens {\n const { runtime, action, subject } = params\n\n if (subject.kind !== \"object\") {\n throw new OntologyValidationError(`Action '${action.id}' requires an object subject.`)\n }\n\n const objectType = runtime.ontology.resolveObjectType(subject.objectTypeId)\n if (!actionAppliesToObjectType(runtime, action, objectType)) {\n throw new OntologyValidationError(\n `Action '${action.id}' is not valid for object type '${objectType.id}'.`\n )\n }\n\n return objectType\n}\n\nfunction actionAppliesToObjectType(\n runtime: Pick<ActionValidationRuntime, \"actionRegistry\">,\n action: ObjectActionDefinition,\n objectType: ObjectTypeWithPropertyTokens\n): boolean {\n return runtime.actionRegistry\n .listForType(objectType)\n .some((candidate) => candidate.id === action.id)\n}\n",
|
|
12
|
+
"export class ShareDefinitionError extends Error {\n readonly name = \"ShareDefinitionError\"\n}\n",
|
|
13
|
+
"import type { ObjectActionDefinition } from \"../actions\"\nimport type { ObjectTypeWithPropertyTokens } from \"../ontology\"\nimport {\n type LinkPathSelection,\n type LinkPathSelectionInput,\n type LinkPathSelectionMode,\n snapshotLinkPathSelection,\n} from \"../ontology/link-path-selection\"\nimport { ShareDefinitionError } from \"./errors\"\nimport type {\n DefineShareOptions,\n ShareActionGrant,\n ShareDefinition,\n ShareScopeGrant,\n ShareTarget,\n ShareViewGrant,\n ShareViewGrantBuilder,\n} from \"./types\"\n\nconst shareTargets = new WeakSet<object>()\n\nexport function defineShare<\n const TId extends string,\n const TTarget extends ObjectTypeWithPropertyTokens,\n const TGrants extends readonly ShareScopeGrant[],\n>(id: TId, options: DefineShareOptions<TTarget, TGrants>): ShareDefinition<TId, TTarget[\"id\"]> {\n assertNonEmpty(id, \"Share id\")\n if (!isObjectType(options.target)) {\n throw invalid(`Share '${id}' target must be an object type.`)\n }\n if (typeof options.grants !== \"function\") {\n throw invalid(`Share '${id}' grants must be a function.`)\n }\n if (options.description !== undefined && typeof options.description !== \"string\") {\n throw invalid(`Share '${id}' description must be a string.`)\n }\n\n const target = createShareTarget(options.target.id)\n let authoredGrants: readonly unknown[]\n try {\n authoredGrants = options.grants({ target })\n } catch (error) {\n if (error instanceof ShareDefinitionError) throw error\n const reason = error instanceof Error ? error.message.replace(/^\\[Sixb\\] /, \"\") : String(error)\n throw invalid(`Share '${id}' grants are invalid: ${reason}`)\n }\n if (!Array.isArray(authoredGrants) || authoredGrants.length === 0) {\n throw invalid(`Share '${id}' must declare at least one grant.`)\n }\n const grants = snapshotShareGrants(id, options.target.id, authoredGrants)\n\n return Object.freeze({\n kind: \"share\" as const,\n id,\n target: Object.freeze({ kind: \"object\" as const, objectTypeId: options.target.id }),\n grants,\n ...(options.description === undefined ? {} : { description: options.description }),\n })\n}\n\nexport function isShareDefinition(value: unknown): value is ShareDefinition {\n if (!isRecord(value) || value.kind !== \"share\" || !isNonEmpty(value.id)) return false\n if (\n !isRecord(value.target) ||\n value.target.kind !== \"object\" ||\n !isNonEmpty(value.target.objectTypeId)\n ) {\n return false\n }\n return Array.isArray(value.grants)\n}\n\n/** @internal Validate, canonicalize, and detach a definition before runtime registration/use. */\nexport function snapshotShareDefinition(value: unknown): ShareDefinition {\n try {\n if (!isRecord(value)) {\n throw invalid(\"Share definition kind must be 'share'.\")\n }\n const kind = value.kind\n const authoredId = value.id\n const target = value.target\n const authoredGrants = value.grants\n const description = value.description\n if (kind !== \"share\") {\n throw invalid(\"Share definition kind must be 'share'.\")\n }\n const id = nonEmpty(authoredId, \"Share id\")\n if (!isRecord(target)) {\n throw invalid(`Share '${id}' target must be an object type.`)\n }\n const targetKind = target.kind\n const authoredObjectTypeId = target.objectTypeId\n if (targetKind !== \"object\" || !isNonEmpty(authoredObjectTypeId)) {\n throw invalid(`Share '${id}' target must be an object type.`)\n }\n if (!Array.isArray(authoredGrants) || authoredGrants.length === 0) {\n throw invalid(`Share '${id}' must declare grants.`)\n }\n if (description !== undefined && typeof description !== \"string\") {\n throw invalid(`Share '${id}' description must be a string.`)\n }\n\n const objectTypeId = authoredObjectTypeId\n return Object.freeze({\n kind: \"share\" as const,\n id,\n target: Object.freeze({ kind: \"object\" as const, objectTypeId }),\n grants: snapshotShareGrants(id, objectTypeId, authoredGrants),\n ...(description === undefined ? {} : { description }),\n })\n } catch (error) {\n if (error instanceof ShareDefinitionError) throw error\n const reason = error instanceof Error ? error.message.replace(/^\\[Sixb\\] /, \"\") : String(error)\n throw invalid(`Share definition is invalid: ${reason}`)\n }\n}\n\n/** @internal Contextual overload used by `can.view(target)`. */\nexport function isShareTarget(value: unknown): value is ShareTarget {\n return typeof value === \"object\" && value !== null && shareTargets.has(value)\n}\n\n/** @internal Contextual overload used by `can.view(target)`. */\nexport function createShareViewGrant<TObjectTypeId extends string>(\n target: ShareTarget<TObjectTypeId>\n): ShareViewGrantBuilder<TObjectTypeId> {\n assertShareTarget(target)\n return createShareViewGrantWithLinks(target.objectTypeId, Object.freeze({ kind: \"none\" }))\n}\n\n/** @internal Contextual overload used by `can.apply(action).on(target)`. */\nexport function createShareActionGrant<TAction extends ObjectActionDefinition>(\n action: TAction,\n target: ShareTarget<TAction[\"binding\"][\"objectType\"][\"id\"]>\n): ShareActionGrant<TAction[\"id\"], TAction[\"binding\"][\"objectType\"][\"id\"]> {\n assertShareTarget(target)\n const objectTypeId = action.binding.objectType.id\n if (target.objectTypeId !== objectTypeId) {\n throw invalid(\n `Action '${action.id}' is defined on '${objectTypeId}', not Share target '${target.objectTypeId}'. Shared Actions are exact-type only in V1.`\n )\n }\n return Object.freeze({\n kind: \"action.apply\" as const,\n actionId: action.id,\n subjectObjectTypeId: target.objectTypeId,\n })\n}\n\nfunction createShareTarget<TObjectTypeId extends string>(\n objectTypeId: TObjectTypeId\n): ShareTarget<TObjectTypeId> {\n const target = { objectTypeId } as ShareTarget<TObjectTypeId>\n shareTargets.add(target)\n return Object.freeze(target)\n}\n\nfunction createShareViewGrantWithLinks<TObjectTypeId extends string>(\n targetObjectTypeId: TObjectTypeId,\n links: LinkPathSelectionMode\n): ShareViewGrantBuilder<TObjectTypeId> {\n const grant = {\n kind: \"object.view\" as const,\n targetObjectTypeId,\n links,\n } as ShareViewGrantBuilder<TObjectTypeId>\n Object.defineProperty(grant, \"withLinks\", {\n configurable: false,\n enumerable: false,\n writable: false,\n value: (...args: [links?: readonly LinkPathSelectionInput<TObjectTypeId>[]]) => {\n if (args.length === 0) {\n return freezeViewGrant(targetObjectTypeId, Object.freeze({ kind: \"all\" }))\n }\n const selected = args[0]\n if (!Array.isArray(selected)) {\n throw invalid(\"withLinks(...) expects an array, or no argument for every direct link.\")\n }\n return freezeViewGrant(\n targetObjectTypeId,\n Object.freeze({\n kind: \"selected\" as const,\n links: Object.freeze(selected.map(snapshotLinkPathSelection)),\n })\n )\n },\n })\n return Object.freeze(grant)\n}\n\nfunction freezeViewGrant<TObjectTypeId extends string>(\n targetObjectTypeId: TObjectTypeId,\n links: LinkPathSelectionMode\n): ShareViewGrant<TObjectTypeId> {\n return Object.freeze({ kind: \"object.view\" as const, targetObjectTypeId, links })\n}\n\nfunction snapshotShareGrants(\n shareId: string,\n targetObjectTypeId: string,\n authored: readonly unknown[]\n): readonly ShareScopeGrant[] {\n const grants: ShareScopeGrant[] = []\n const actionIds = new Set<string>()\n let viewCount = 0\n\n for (let index = 0; index < authored.length; index += 1) {\n const grant = authored[index]\n if (!isRecord(grant)) {\n throw invalid(`Share '${shareId}' grant ${index} must come from 'can'.`)\n }\n const kind = grant.kind\n if (kind === \"object.view\") {\n const authoredTargetObjectTypeId = grant.targetObjectTypeId\n const links = grant.links\n if (authoredTargetObjectTypeId !== targetObjectTypeId) {\n throw invalid(`Share '${shareId}' view grant must use its contextual target.`)\n }\n viewCount += 1\n if (viewCount > 1) {\n throw invalid(`Share '${shareId}' must declare exactly one view grant.`)\n }\n grants.push(\n Object.freeze({\n kind: \"object.view\" as const,\n targetObjectTypeId,\n links: snapshotLinkMode(links),\n })\n )\n continue\n }\n if (kind === \"action.apply\") {\n const actionId = grant.actionId\n const subjectObjectTypeId = grant.subjectObjectTypeId\n if (!isNonEmpty(actionId) || subjectObjectTypeId !== targetObjectTypeId) {\n throw invalid(`Share '${shareId}' action grant must apply to its contextual target.`)\n }\n if (actionIds.has(actionId)) {\n throw invalid(`Share '${shareId}' contains duplicate action '${actionId}'.`)\n }\n actionIds.add(actionId)\n grants.push(\n Object.freeze({\n kind: \"action.apply\" as const,\n actionId,\n subjectObjectTypeId: targetObjectTypeId,\n })\n )\n continue\n }\n throw invalid(`Share '${shareId}' grant ${index} must come from 'can'.`)\n }\n\n if (viewCount !== 1) {\n throw invalid(`Share '${shareId}' must declare exactly one can.view(target) grant.`)\n }\n return Object.freeze(grants)\n}\n\nfunction snapshotLinkMode(value: unknown): LinkPathSelectionMode {\n if (!isRecord(value)) throw invalid(\"Share link selection must be an object.\")\n const kind = value.kind\n const links = value.links\n if (kind === \"none\" || kind === \"all\") {\n return Object.freeze({ kind })\n }\n if (kind !== \"selected\" || !Array.isArray(links)) {\n throw invalid(\"Share link selection must be none, all, or selected links.\")\n }\n if (links.length === 0) {\n throw invalid(\"withLinks([]) is empty; omit withLinks() when no links should be shared.\")\n }\n try {\n return Object.freeze({\n kind: \"selected\" as const,\n links: snapshotLinkPaths(links),\n })\n } catch (error) {\n if (error instanceof ShareDefinitionError) throw error\n const reason = error instanceof Error ? error.message.replace(/^\\[Sixb\\] /, \"\") : String(error)\n throw invalid(`Share link selection is invalid: ${reason}`)\n }\n}\n\nfunction snapshotLinkPaths(values: readonly unknown[]): readonly LinkPathSelection[] {\n const byKey = new Map<string, LinkPathSelection>()\n for (const value of values) {\n const captured = canonicalizeLinkPath(\n snapshotLinkPathSelection(value as LinkPathSelectionInput)\n )\n const key = JSON.stringify([captured.sourceObjectTypeId, captured.linkId])\n const current = byKey.get(key)\n if (!current) {\n byKey.set(key, captured)\n continue\n }\n if (!sameLinkTargets(current.targetObjectTypeId, captured.targetObjectTypeId)) {\n throw invalid(\n `Link '${captured.sourceObjectTypeId}.${captured.linkId}' declares inconsistent targets.`\n )\n }\n byKey.set(\n key,\n Object.freeze({\n ...current,\n selection: mergeLinkModes(current.selection, captured.selection),\n })\n )\n }\n return Object.freeze([...byKey.values()])\n}\n\nfunction canonicalizeLinkPath(value: LinkPathSelection): LinkPathSelection {\n return Object.freeze({\n ...value,\n selection:\n value.selection.kind === \"selected\"\n ? Object.freeze({\n kind: \"selected\" as const,\n links: snapshotLinkPaths(value.selection.links),\n })\n : value.selection,\n })\n}\n\nfunction mergeLinkModes(\n left: LinkPathSelectionMode,\n right: LinkPathSelectionMode\n): LinkPathSelectionMode {\n if (left.kind === \"all\" || right.kind === \"all\") return Object.freeze({ kind: \"all\" })\n if (left.kind === \"none\") return right\n if (right.kind === \"none\") return left\n return Object.freeze({\n kind: \"selected\" as const,\n links: snapshotLinkPaths([...left.links, ...right.links]),\n })\n}\n\nfunction sameLinkTargets(\n left: string | readonly string[],\n right: string | readonly string[]\n): boolean {\n if (typeof left === \"string\" || typeof right === \"string\") return left === right\n return left.length === right.length && left.every((value, index) => value === right[index])\n}\n\nfunction assertShareTarget(value: unknown): asserts value is ShareTarget {\n if (!isShareTarget(value)) {\n throw invalid(\"Shared grants must use the target provided by defineShare(...).\")\n }\n}\n\nfunction isObjectType(value: unknown): value is ObjectTypeWithPropertyTokens {\n return (\n isRecord(value) &&\n isNonEmpty(value.id) &&\n Array.isArray(value.properties) &&\n Array.isArray(value.links)\n )\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction isNonEmpty(value: unknown): value is string {\n return typeof value === \"string\" && value.trim().length > 0\n}\n\nfunction assertNonEmpty(value: unknown, field: string): asserts value is string {\n if (!isNonEmpty(value)) throw invalid(`${field} must not be empty.`)\n}\n\nfunction nonEmpty(value: unknown, field: string): string {\n assertNonEmpty(value, field)\n return value\n}\n\nfunction invalid(message: string): ShareDefinitionError {\n return new ShareDefinitionError(`[Sixb] ${message}`)\n}\n",
|
|
14
|
+
"import type { ProjectReference } from \"./types\"\n\n/**\n * Project-wide surfaces used in security grants such as `can.observe(project.logs)`,\n * `can.view(project.users)` and `can.run(project.models)`.\n */\nexport const project: ProjectReference = Object.freeze({\n kind: \"project\",\n logs: Object.freeze({ kind: \"logs\" }),\n activity: Object.freeze({ kind: \"activity\" }),\n users: Object.freeze({ kind: \"users\" }),\n models: Object.freeze({ kind: \"models\" }),\n})\n",
|
|
15
|
+
"/**\n * Grant builders for role definitions.\n *\n * Grants are plain data referencing 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, ObjectActionDefinition } from \"../actions/types\"\nimport { isObjectActionDefinition } from \"../actions/validation\"\nimport type {\n AgentMemoryReference,\n AgentReference,\n AgentThreadsReference,\n AgentUsageReference,\n} from \"../agents/types\"\nimport type { ConnectorDefinition } from \"../connectors\"\nimport type { DatasetDefinition } from \"../datasets\"\nimport { resolveWhere } from \"../objects/sdk/where\"\nimport type { ObjectType, ObjectTypeWithPropertyTokens } from \"../ontology\"\nimport type { PipelineDefinition } from \"../pipelines\"\nimport { createShareActionGrant, createShareViewGrant, isShareTarget } from \"../shares/builders\"\nimport type {\n ShareActionGrantBuilder,\n ShareDefinition,\n ShareTarget,\n ShareViewGrantBuilder,\n} from \"../shares/types\"\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 { project } from \"./project\"\nimport type {\n AgentRunGrant,\n AppendGrant,\n ApplyGrant,\n EditGrant,\n ManageGrant,\n ModelsRunGrant,\n ObjectViewGrantBuilder,\n ObserveGrant,\n ProjectReference,\n RunGrant,\n Selection,\n ShareGrant,\n UsersViewGrant,\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 * Six of the eight 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 connector: \"connector\",\n share: \"share\",\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\": object and action 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\n/** `project` itself and the surfaces of it that are not viewed, which `can.view` rejects. */\nconst UNVIEWABLE_PROJECT_REFERENCES: ReadonlySet<unknown> = new Set([\n project,\n project.logs,\n project.activity,\n])\n\nfunction view<const TObjectTypeId extends string>(\n input: ShareTarget<TObjectTypeId>\n): ShareViewGrantBuilder<TObjectTypeId>\nfunction view(input: ProjectReference[\"users\"]): UsersViewGrant\nfunction view<const TObjectType extends ObjectTypeWithPropertyTokens>(\n input: TObjectType\n): ObjectViewGrantBuilder<TObjectType>\nfunction view(input: GrantInput<ObjectType, \"object\">): ViewGrant<\"object\">\nfunction view(input: GrantInput<DatasetDefinition, \"dataset\">): ViewGrant<\"dataset\">\nfunction view(\n input:\n | ShareTarget\n | ProjectReference[\"users\"]\n | GrantInput<ObjectType | DatasetDefinition, \"object\" | \"dataset\">\n): ViewGrant | UsersViewGrant | ShareViewGrantBuilder {\n if (isShareTarget(input)) return createShareViewGrant(input)\n\n if (isUsersReference(input)) {\n return { kind: \"grant\", capability: \"view\", target: \"users\" }\n }\n\n // `project` and its other surfaces would otherwise read as an object type with no id.\n if (UNVIEWABLE_PROJECT_REFERENCES.has(input)) {\n throw new SecurityValidationError(\n \"[Sixb] can.view accepts object types, datasets, shares, or project.users.\"\n )\n }\n\n const { target, selection } = resolveGrant(input, \"can.view\", VIEW_TARGETS)\n const grant: ViewGrant = { kind: \"grant\", capability: \"view\", target, selection }\n\n // Only a grant on one object type takes a condition, since a condition reads that type's\n // properties. As in `apply`, the cast restores the branch `Array.isArray` cannot narrow.\n const one: ObjectType | undefined =\n target !== \"object\" || Array.isArray(input) || isBreadthSelector(input)\n ? undefined\n : (input as ObjectType)\n\n if (one) {\n Object.defineProperty(grant, \"where\", {\n configurable: false,\n enumerable: false,\n writable: false,\n value: (callback: unknown) => conditionalViewGrant(grant, one, callback),\n })\n }\n\n return grant\n}\n\n/**\n * The condition is built once, here, with the same builder and the same conversion as an object\n * query's `.where()`. Startup validates it against the ontology.\n */\nfunction conditionalViewGrant(\n grant: ViewGrant,\n objectType: ObjectType,\n callback: unknown\n): ViewGrant<\"object\"> {\n const subject = `can.view(${objectType.id}).where(...)`\n\n if (typeof callback !== \"function\") {\n throw new SecurityValidationError(\n `[Sixb] ${subject} expects a function, such as (object) => object.p.status.eq(\"open\").`\n )\n }\n\n const condition = resolveWhere(callback as Parameters<typeof resolveWhere>[0])\n if (condition === undefined) {\n throw new SecurityValidationError(\n `[Sixb] ${subject} returned no condition. Return a predicate, or drop .where() to grant every object.`\n )\n }\n\n return deepFreeze({\n kind: \"grant\",\n capability: \"view\",\n target: \"object\",\n selection: structuredClone(grant.selection),\n condition: structuredClone(condition),\n })\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value\n\n for (const child of Object.values(value)) deepFreeze(child)\n return Object.freeze(value)\n}\n\nfunction isUsersReference(input: unknown): input is ProjectReference[\"users\"] {\n return (\n typeof input === \"object\" &&\n input !== null &&\n !Array.isArray(input) &&\n !isBreadthSelector(input) &&\n \"kind\" in input &&\n input.kind === \"users\"\n )\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<const TAction extends ObjectActionDefinition>(\n input: TAction\n): ApplyGrant & ShareActionGrantBuilder<TAction>\nfunction apply(input: GrantInput<ActionDefinition, \"action\">): ApplyGrant\nfunction apply(input: GrantInput<ActionDefinition, \"action\">): ApplyGrant {\n const grant: ApplyGrant = {\n kind: \"grant\",\n capability: \"apply\",\n selection: resolveGrant(input, \"can.apply\", [\"action\"]).selection,\n }\n // `Array.isArray` does not narrow a readonly array. This cast restores the branch already proved\n // above; every non-selector, non-array GrantInput is one Action definition.\n const one: ActionDefinition | undefined =\n Array.isArray(input) || isBreadthSelector(input) ? undefined : (input as ActionDefinition)\n if (one && isObjectActionDefinition(one)) {\n Object.defineProperty(grant, \"on\", {\n configurable: false,\n enumerable: false,\n writable: false,\n value: (target: ShareTarget) => createShareActionGrant(one, target),\n })\n }\n return grant\n}\n\nfunction share(input: GrantInput<ShareDefinition, \"share\">): ShareGrant {\n return {\n kind: \"grant\",\n capability: \"share\",\n selection: resolveGrant(input, \"can.share\", [\"share\"]).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(input: ProjectReference[\"models\"]): ModelsRunGrant\nfunction run(\n input:\n | AgentReference\n | ProjectReference[\"models\"]\n | GrantInput<\n WorkflowDefinition | SyncDefinition | PipelineDefinition,\n \"workflow\" | \"sync\" | \"pipeline\"\n >\n): RunGrant | AgentRunGrant | ModelsRunGrant {\n if (isAgentReference(input)) {\n return { kind: \"grant\", capability: \"run\", target: \"agent\" }\n }\n if (isModelsReference(input)) {\n return { kind: \"grant\", capability: \"run\", target: \"models\" }\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 isModelsReference(input: unknown): input is ProjectReference[\"models\"] {\n return (\n typeof input === \"object\" &&\n input !== null &&\n !Array.isArray(input) &&\n !isBreadthSelector(input) &&\n \"kind\" in input &&\n input.kind === \"models\"\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\n/**\n * Listed member by member: a `project` surface is not observable just by existing.\n * `project.users` is read with `can.view`.\n */\ntype ObservableReference =\n | ProjectReference[\"logs\"]\n | ProjectReference[\"activity\"]\n | AgentUsageReference\n | AgentThreadsReference\n\n/**\n * Every reference `can.observe` accepts, keyed by its `kind`, which is also its grant target. The\n * full `Record` is what stops a new observable reference from compiling until it is listed here.\n */\nconst OBSERVABLE_REFERENCES: Readonly<Record<ObservableReference[\"kind\"], string>> = {\n logs: \"project.logs\",\n activity: \"project.activity\",\n aiUsage: \"agent.usage\",\n agentThreads: \"agent.threads\",\n}\n\nfunction isObservableReference(input: unknown): input is ObservableReference {\n return (\n typeof input === \"object\" &&\n input !== null &&\n \"kind\" in input &&\n typeof input.kind === \"string\" &&\n Object.hasOwn(OBSERVABLE_REFERENCES, input.kind)\n )\n}\n\nfunction observe(input: ObservableReference): ObserveGrant {\n const value: unknown = input\n\n // Older role files pass the string form. Point them at the reference instead of only rejecting\n // the input.\n if (value === \"logs\") {\n throw new SecurityValidationError(\n '[Sixb] can.observe(\"logs\") is now can.observe(project.logs), imported from \"@sixb/core\".'\n )\n }\n\n if (!isObservableReference(value)) {\n const accepted = Object.values(OBSERVABLE_REFERENCES).join(\" or \")\n throw new SecurityValidationError(`[Sixb] can.observe accepts ${accepted}.`)\n }\n\n return { kind: \"grant\", capability: \"observe\", target: value.kind }\n}\n\nfunction isAgentMemoryReference(input: unknown): input is AgentMemoryReference {\n return (\n typeof input === \"object\" &&\n input !== null &&\n !Array.isArray(input) &&\n !isBreadthSelector(input) &&\n \"kind\" in input &&\n input.kind === \"agentMemory\"\n )\n}\n\nfunction manage(input: GrantInput<ConnectorDefinition, \"connector\">): ManageGrant<\"connector\">\nfunction manage(input: AgentUsageReference): ManageGrant<\"aiUsage\">\nfunction manage(input: AgentMemoryReference): ManageGrant<\"agentMemory\">\nfunction manage(\n input: GrantInput<ConnectorDefinition, \"connector\"> | AgentUsageReference | AgentMemoryReference\n): ManageGrant {\n if (isAgentUsageReference(input)) {\n return { kind: \"grant\", capability: \"manage\", target: \"aiUsage\" }\n }\n if (isAgentMemoryReference(input)) {\n return { kind: \"grant\", capability: \"manage\", target: \"agentMemory\" }\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 view,\n edit,\n append,\n apply,\n share,\n run,\n observe,\n manage,\n}\n",
|
|
16
|
+
"import { isCurrentUser, type UserRef } from \"../../ontology/user-ref\"\nimport type { ObjectQuery, ObjectQueryPredicate } from \"./ir\"\n\n/**\n * Replace every `currentUser()` of a validated query with the reader's user reference.\n *\n * Validation admits the placeholder only where a predicate compares user references, so storage\n * never receives it. Without a user, as for a service account, a schedule, or a share, `eq`, `in`\n * and `contains` become a constant that matches nothing, and `neq` one that matches every row: it\n * stays the complement of `eq`.\n *\n * The bound query is valid again and holds no placeholder: the executor validates parts of it\n * once more, and binding it twice changes nothing.\n */\nexport function bindCurrentUser(query: ObjectQuery, user: UserRef | undefined): ObjectQuery {\n switch (query.kind) {\n case \"start\":\n case \"refs\":\n return query\n case \"filter\":\n return {\n ...query,\n input: bindCurrentUser(query.input, user),\n predicate: bindCurrentUserPredicate(query.predicate, user),\n }\n case \"set\":\n return { ...query, inputs: query.inputs.map((input) => bindCurrentUser(input, user)) }\n default:\n return { ...query, input: bindCurrentUser(query.input, user) }\n }\n}\n\n/** Replace every `currentUser()` of a validated predicate, with the rules of {@link bindCurrentUser}. */\nexport function bindCurrentUserPredicate(\n predicate: ObjectQueryPredicate,\n user: UserRef | undefined\n): ObjectQueryPredicate {\n switch (predicate.op) {\n case \"and\":\n case \"or\":\n return {\n ...predicate,\n items: predicate.items.map((item) => bindCurrentUserPredicate(item, user)),\n }\n case \"not\":\n return { ...predicate, item: bindCurrentUserPredicate(predicate.item, user) }\n case \"exists\":\n case \"constant\":\n return predicate\n case \"in\": {\n if (!predicate.values.some(isCurrentUser)) return predicate\n\n const values = predicate.values.flatMap((value) =>\n isCurrentUser(value) ? (user ? [user] : []) : [value]\n )\n return values.length > 0 ? { ...predicate, values } : NO_ROW\n }\n case \"contains\": {\n if (!isCurrentUser(predicate.value)) return predicate\n if (user) return { ...predicate, value: user }\n\n return NO_ROW\n }\n default: {\n if (!isCurrentUser(predicate.value)) return predicate\n if (user) return { ...predicate, value: user }\n\n return predicate.op === \"neq\" ? EVERY_ROW : NO_ROW\n }\n }\n}\n\n// A constant rather than a comparison with a reserved user id: auth strategies choose user ids, so\n// any id could one day name a real user.\nconst NO_ROW: ObjectQueryPredicate = Object.freeze({ op: \"constant\", value: false })\nconst EVERY_ROW: ObjectQueryPredicate = Object.freeze({ op: \"constant\", value: true })\n",
|
|
17
|
+
"import { MaterializationValidationError } from \"../../materialization/errors\"\nimport { sha256Canonical } from \"../../materialization/identity\"\nimport type { ObjectVectorSearchProfile } from \"../../ontology/types\"\n\nexport const MAX_VECTOR_K = 1000\nexport const VECTOR_INPUT_VERSION = 1\n/**\n * Nobody waits on indexing, and the provider bills a call whose response is abandoned. The\n * deadline only frees the worker from a dead connection, so it is far longer than a search's.\n */\nexport const INDEXING_EMBEDDING_TIMEOUT_MS = 5 * 60_000\n\nexport function vectorConfiguration(profile: ObjectVectorSearchProfile): string {\n return sha256Canonical({\n format: VECTOR_INPUT_VERSION,\n sources: [...profile.source],\n provider: profile.model.providerId,\n model: profile.model.modelId,\n representation: profile.model.definition.representation ?? { name: profile.model.modelId },\n dimensions: profile.model.definition.dimensions,\n // Include retrieval preparation without changing existing symmetric identities.\n ...(profile.model.definition.inputMode === \"asymmetric\" ? { inputMode: \"asymmetric\" } : {}),\n metric: \"cosine\",\n precision: \"float32\",\n normalization: \"l2-v1\",\n })\n}\n\nexport function vectorSources(\n source: readonly string[],\n properties: Readonly<Record<string, unknown>>\n) {\n const values: Record<string, string | null> = Object.create(null)\n for (const key of source) {\n const value = properties[key]\n if (value !== undefined && value !== null && typeof value !== \"string\") {\n throw new MaterializationValidationError(`Vector source must be text: ${key}`)\n }\n values[key] = typeof value === \"string\" ? value : null\n }\n // Ordered JSON pairs preserve field boundaries, escaping and absent/empty distinction.\n const text = JSON.stringify(source.map((key) => [key, values[key]]))\n return { text, sourceFingerprint: sha256Canonical(text) }\n}\n\n/** Unit-length float32 representation keeps native cosine arithmetic within range. */\nexport function normalizeVector(values: readonly number[], dimensions: number): readonly number[] {\n if (!Array.isArray(values) || values.length !== dimensions) {\n throw new MaterializationValidationError(`Vector dimension mismatch; expected ${dimensions}`)\n }\n const normalized = Array.from(values, (value) => {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n !Number.isFinite(Math.fround(value))\n ) {\n throw new MaterializationValidationError(\"Vector values must be finite float32 numbers.\")\n }\n return Math.fround(value)\n })\n if (!normalized.some((value) => value !== 0)) {\n throw new MaterializationValidationError(\"Cosine search requires a nonzero vector.\")\n }\n const norm = Math.hypot(...normalized)\n return Object.freeze(normalized.map((value) => Math.fround(value / norm)))\n}\n\n/** V1 envelope for exact SQL scoring; exceeding it must fail rather than truncate candidates. */\nexport function vectorSearchCandidateLimit(dimensions: number): number {\n return Math.min(10000, Math.floor(16000000 / dimensions))\n}\n",
|
|
18
|
+
"import type { ObjectQuery } from \"../query/ir\"\n\nexport function hasVectorProfile(query: ObjectQuery): boolean {\n if (query.kind === \"vector\") return true\n if (query.kind === \"set\") return query.inputs.some(hasVectorProfile)\n return \"input\" in query && hasVectorProfile(query.input)\n}\n\n/** Rank one eligible object set; validation resolves its type and admits every traversed edge. */\nexport function isVectorProfileQuery(query: ObjectQuery): boolean {\n if (query.kind === \"limit\" || query.kind === \"project\") return isVectorProfileQuery(query.input)\n if (query.kind === \"rerank\") {\n return query.input.kind === \"vector\" && isVectorProfileQuery(query.input)\n }\n if (query.kind !== \"vector\" || !query.profile) return false\n return isVectorCandidateQuery(query.input)\n}\n\nfunction isVectorCandidateQuery(query: ObjectQuery): boolean {\n switch (query.kind) {\n case \"start\":\n return !query.includeSubtypes\n case \"refs\":\n return true\n case \"filter\":\n case \"traverse\":\n return isVectorCandidateQuery(query.input)\n case \"set\":\n return query.inputs.every(isVectorCandidateQuery)\n default:\n return false\n }\n}\n",
|
|
19
|
+
"// Bound synchronous inference independently of the storage's vector-search capacity.\nexport const MAX_RERANK_CANDIDATES = 100\nexport const MAX_RERANK_INPUT_BYTES = 1_048_576\n",
|
|
20
|
+
"import type {\n ObjectRef,\n ObjectType,\n OntologyRegistry,\n Property,\n Schema,\n ValueType,\n} from \"../../ontology\"\nimport { normalizeDecimalValue } from \"../../ontology\"\nimport { formatUnknownObjectTypeMessage } from \"../../ontology/errors\"\nimport {\n isContainsSchema,\n isExactSchema,\n isSortableSchema,\n isTextSchema,\n queryScalarKindForSchema,\n} from \"../../ontology/query-capabilities\"\nimport { isCurrentUser, isUserRefPropertySchema } from \"../../ontology/user-ref\"\nimport {\n normalizeSchemaValue,\n validatePropertyValue,\n validateSchemaValue,\n} from \"../../ontology/validation\"\nimport { MAX_VECTOR_K, normalizeVector, vectorConfiguration } from \"../vectors/profile\"\nimport { hasVectorProfile, isVectorProfileQuery } from \"../vectors/query\"\nimport { ObjectQueryValidationError } from \"./errors\"\nimport type {\n ObjectExpansion,\n ObjectQuery,\n ObjectQueryDirection,\n ObjectQueryPredicate,\n ObjectQueryResultShape,\n ObjectQuerySetOperation,\n ObjectQuerySortField,\n ObjectQueryVector,\n QueryScalarKind,\n} from \"./ir\"\nimport { normalizeObjectQuery } from \"./normalize\"\nimport { MAX_RERANK_CANDIDATES } from \"./reranking-limits\"\n\nexport interface ObjectQueryValidationIssue {\n path: string\n code: string\n message: string\n}\n\nexport interface ValidatedObjectQuery {\n query: ObjectQuery\n result: ObjectQueryResultShape\n /**\n * Every object type the query touches, including intermediate traversal types and the subtypes\n * an outgoing link can reach.\n */\n touchedObjectTypeIds: readonly string[]\n}\n\nexport interface ObjectQueryValidationOptions {\n ontology: OntologyRegistry\n maxLimit?: number\n maxPageSize?: number\n maxRefs?: number\n normalize?: boolean\n}\n\n/** Opaque semantic state carried by the canonical query validator for an internal admission. */\nexport type ObjectQueryAdmissionState = object\n\nexport type ObjectQueryPropertyUse =\n | \"filter\"\n | \"text\"\n | \"vector\"\n | \"sort\"\n | \"project\"\n | \"expand.orderBy\"\n | \"facet\"\n\nexport type ObjectQueryEdgeUse = \"traverse\" | \"expand\" | \"queryLinks\"\n\nexport interface ObjectQueryAdmissionTransition {\n readonly state: ObjectQueryAdmissionState\n /** Recorded during the walk and raised only after ordinary validation succeeds. */\n readonly denial?: Error\n}\n\n/**\n * Internal semantic admission reducer driven by the canonical query validator.\n *\n * It deliberately has no AST visitor: validation owns recursion through query nodes, predicates,\n * and expansions, while an admission only reduces the semantic sources, properties, edges, and\n * set operations it observes.\n */\nexport interface ObjectQuerySemanticAdmission {\n empty(): ObjectQueryAdmissionState\n source(input: {\n readonly kind: \"start\" | \"refs\"\n readonly result: ObjectQueryResultShape\n readonly objectTypeId?: string\n readonly refs?: readonly ObjectRef[]\n readonly path: string\n }): ObjectQueryAdmissionTransition\n property(input: {\n readonly state: ObjectQueryAdmissionState\n readonly propertyId: string\n readonly objectTypeId?: string\n readonly use: ObjectQueryPropertyUse\n readonly path: string\n }): Error | undefined\n edge(input: {\n readonly state: ObjectQueryAdmissionState\n /** Ontology-resolved shape after following this edge. */\n readonly result: ObjectQueryResultShape\n readonly linkId: string\n readonly direction: ObjectQueryDirection\n readonly sourceObjectTypeId?: string\n readonly use: ObjectQueryEdgeUse\n readonly path: string\n }): ObjectQueryAdmissionTransition\n set(input: {\n readonly op: ObjectQuerySetOperation\n readonly states: readonly ObjectQueryAdmissionState[]\n readonly path: string\n }): ObjectQueryAdmissionState\n}\n\nexport interface AdmittedObjectQuery extends ValidatedObjectQuery {\n /** Root provenance for terminal-specific checks such as facets and physical link queries. */\n admissionState: ObjectQueryAdmissionState\n}\n\ntype QueryValidationContext = Required<\n Pick<ObjectQueryValidationOptions, \"maxLimit\" | \"maxPageSize\" | \"maxRefs\">\n> & {\n ontology: OntologyRegistry\n valueTypesById: ReadonlyMap<string, ValueType>\n issues: ObjectQueryValidationIssue[]\n touchedObjectTypeIds: Set<string>\n admission: ObjectQuerySemanticAdmission\n admissionDenials: Error[]\n}\n\ninterface QueryNodeValidation {\n result: ObjectQueryResultShape\n query: ObjectQuery\n}\n\ninterface QueryValidationResult extends QueryNodeValidation {\n admissionState: ObjectQueryAdmissionState\n}\n\ninterface TextFieldResolution {\n fieldsByObjectType?: Record<string, string[]>\n}\n\nconst DEFAULT_MAX_LIMIT = 1_000\nconst DEFAULT_MAX_PAGE_SIZE = 1_000\nconst DEFAULT_MAX_REFS = 1_000\n\nconst NOOP_ADMISSION_STATE = Object.freeze({})\nconst NOOP_QUERY_ADMISSION: ObjectQuerySemanticAdmission = Object.freeze({\n empty: () => NOOP_ADMISSION_STATE,\n source: () => ({ state: NOOP_ADMISSION_STATE }),\n property: () => undefined,\n edge: (input: Parameters<ObjectQuerySemanticAdmission[\"edge\"]>[0]) => ({\n state: input.state,\n }),\n set: (input: Parameters<ObjectQuerySemanticAdmission[\"set\"]>[0]) =>\n input.states[0] ?? NOOP_ADMISSION_STATE,\n})\n\n/**\n * Admit a query only when both admissions admit it, each reducing its own state.\n *\n * The first denial wins, in order, so composing keeps each admission's messages unchanged.\n */\nexport function composeObjectQueryAdmissions(\n first: ObjectQuerySemanticAdmission,\n second: ObjectQuerySemanticAdmission\n): ObjectQuerySemanticAdmission {\n const parts = new WeakMap<\n ObjectQueryAdmissionState,\n readonly [ObjectQueryAdmissionState, ObjectQueryAdmissionState]\n >()\n const join = (\n left: ObjectQueryAdmissionState,\n right: ObjectQueryAdmissionState\n ): ObjectQueryAdmissionState => {\n const state = Object.freeze({})\n parts.set(state, [left, right])\n return state\n }\n const split = (state: ObjectQueryAdmissionState) => {\n const pair = parts.get(state)\n if (!pair) throw new Error(\"[Sixb] Composed query admission received a foreign state.\")\n return pair\n }\n const transition = (\n left: ObjectQueryAdmissionTransition,\n right: ObjectQueryAdmissionTransition\n ): ObjectQueryAdmissionTransition => {\n const denial = left.denial ?? right.denial\n return { state: join(left.state, right.state), ...(denial ? { denial } : {}) }\n }\n\n const admission: ObjectQuerySemanticAdmission = {\n empty: () => join(first.empty(), second.empty()),\n source: (input) => transition(first.source(input), second.source(input)),\n edge: (input) => {\n const [left, right] = split(input.state)\n return transition(\n first.edge({ ...input, state: left }),\n second.edge({ ...input, state: right })\n )\n },\n property: (input) => {\n const [left, right] = split(input.state)\n return (\n first.property({ ...input, state: left }) ?? second.property({ ...input, state: right })\n )\n },\n set: (input) => {\n const pairs = input.states.map(split)\n return join(\n first.set({ ...input, states: pairs.map(([left]) => left) }),\n second.set({ ...input, states: pairs.map(([, right]) => right) })\n )\n },\n }\n return Object.freeze(admission)\n}\n\nexport function validateObjectQuery(\n query: ObjectQuery,\n options: ObjectQueryValidationOptions\n): ValidatedObjectQuery {\n const admitted = validateObjectQueryWithAdmission(query, options, NOOP_QUERY_ADMISSION)\n return {\n query: admitted.query,\n result: admitted.result,\n touchedObjectTypeIds: admitted.touchedObjectTypeIds,\n }\n}\n\n/**\n * Validate and semantically admit one query in the same canonical walk.\n *\n * This is an internal direct-file API. It is intentionally absent from public query barrels.\n */\nexport function validateObjectQueryWithAdmission(\n query: ObjectQuery,\n options: ObjectQueryValidationOptions,\n admission: ObjectQuerySemanticAdmission\n): AdmittedObjectQuery {\n const normalized = options.normalize === false ? query : normalizeObjectQuery(query)\n const ctx = createValidationContext(options, admission)\n validateVectorComposition(query, ctx)\n const validation = validateQueryNode(normalized, \"$\", ctx)\n\n if (ctx.issues.length > 0) {\n throw new ObjectQueryValidationError(ctx.issues)\n }\n const denial = ctx.admissionDenials[0]\n if (denial) throw denial\n\n return {\n query: validation.query,\n result: validation.result,\n touchedObjectTypeIds: [...ctx.touchedObjectTypeIds],\n admissionState: validation.admissionState,\n }\n}\n\nexport function collectObjectQueryValidationIssues(\n query: ObjectQuery,\n options: ObjectQueryValidationOptions\n): readonly ObjectQueryValidationIssue[] {\n const normalized = options.normalize === false ? query : normalizeObjectQuery(query)\n const ctx = createValidationContext(options, NOOP_QUERY_ADMISSION)\n validateVectorComposition(query, ctx)\n validateQueryNode(normalized, \"$\", ctx)\n return ctx.issues\n}\n\nexport function resolveObjectQueryResultShape(\n query: ObjectQuery,\n options: ObjectQueryValidationOptions\n): ObjectQueryResultShape {\n return validateObjectQuery(query, options).result\n}\n\nfunction validateVectorComposition(query: ObjectQuery, ctx: QueryValidationContext): void {\n if (hasVectorProfile(query) && !isVectorProfileQuery(query))\n ctx.issues.push({\n path: \"$\",\n code: \"vector.composition\",\n message:\n \"Vector profiles support one top-k over one concrete type, with filters, traversals or sets before ranking, optional reranking, then limit/project.\",\n })\n}\n\nfunction createValidationContext(\n options: ObjectQueryValidationOptions,\n admission: ObjectQuerySemanticAdmission\n): QueryValidationContext {\n return {\n ontology: options.ontology,\n valueTypesById: options.ontology.getValueTypesById(),\n maxLimit: options.maxLimit ?? DEFAULT_MAX_LIMIT,\n maxPageSize: options.maxPageSize ?? DEFAULT_MAX_PAGE_SIZE,\n maxRefs: options.maxRefs ?? DEFAULT_MAX_REFS,\n issues: [],\n touchedObjectTypeIds: new Set<string>(),\n admission,\n admissionDenials: [],\n }\n}\n\nfunction validateQueryNode(\n query: ObjectQuery,\n path: string,\n ctx: QueryValidationContext\n): QueryValidationResult {\n const validation = dispatchQueryNode(query, path, ctx)\n\n // Record every intermediate result shape so callers can authorize all\n // object types a query touches, not just the types it returns.\n for (const objectTypeId of validation.result.objectTypeIds) {\n ctx.touchedObjectTypeIds.add(objectTypeId)\n }\n\n return validation\n}\n\nfunction dispatchQueryNode(\n query: ObjectQuery,\n path: string,\n ctx: QueryValidationContext\n): QueryValidationResult {\n switch (query.kind) {\n case \"start\": {\n const validation = validateStart(query.objectTypeId, query.includeSubtypes, path, ctx)\n return {\n ...validation,\n admissionState: admitTransition(\n ctx,\n ctx.admission.source({\n kind: \"start\",\n result: validation.result,\n objectTypeId: query.objectTypeId,\n path,\n })\n ),\n }\n }\n case \"refs\": {\n const validation = validateRefs(query.refs, path, ctx)\n return {\n ...validation,\n admissionState: admitTransition(\n ctx,\n ctx.admission.source({\n kind: \"refs\",\n result: validation.result,\n refs: validation.query.kind === \"refs\" ? validation.query.refs : query.refs,\n path,\n })\n ),\n }\n }\n case \"filter\": {\n const input = validateQueryNode(query.input, `${path}.input`, ctx)\n const predicate = validatePredicate(\n query.predicate,\n input.result,\n input.admissionState,\n `${path}.predicate`,\n ctx\n )\n return {\n result: input.result,\n query: { ...query, input: input.query, predicate },\n admissionState: input.admissionState,\n }\n }\n case \"text\": {\n const input = validateQueryNode(query.input, `${path}.input`, ctx)\n const textFields = validateTextQuery(\n query.query,\n query.fields,\n input.result,\n input.admissionState,\n path,\n ctx\n )\n return {\n result: input.result,\n query: {\n ...query,\n input: input.query,\n fields: query.fields,\n fieldsByObjectType: query.fields ? undefined : textFields.fieldsByObjectType,\n },\n admissionState: input.admissionState,\n }\n }\n case \"vector\": {\n const input = validateQueryNode(query.input, `${path}.input`, ctx)\n return {\n result: input.result,\n query: validateVectorProfileQuery(\n { ...query, input: input.query },\n input.result,\n input.admissionState,\n path,\n ctx\n ),\n admissionState: input.admissionState,\n }\n }\n case \"traverse\": {\n const input = validateQueryNode(query.input, `${path}.input`, ctx)\n const result = validateTraverse(\n query.linkId,\n query.direction,\n query.sourceObjectTypeId,\n input.result,\n path,\n ctx\n )\n return {\n result,\n query: { ...query, input: input.query },\n admissionState: admitTransition(\n ctx,\n ctx.admission.edge({\n state: input.admissionState,\n result,\n linkId: query.linkId,\n direction: query.direction,\n sourceObjectTypeId: query.sourceObjectTypeId,\n use: \"traverse\",\n path,\n })\n ),\n }\n }\n case \"rerank\": {\n const input = validateQueryNode(query.input, `${path}.input`, ctx)\n if (\n input.query.kind !== \"vector\" ||\n typeof input.query.vector !== \"string\" ||\n input.query.k > MAX_RERANK_CANDIDATES\n ) {\n addIssue(\n ctx,\n path,\n \"invalid_rerank_input\",\n `Reranking requires a text vector query with k at most ${MAX_RERANK_CANDIDATES}, before limit or project.`\n )\n }\n if (\n typeof query.model?.provider !== \"string\" ||\n !query.model.provider.trim() ||\n query.model.provider.trim() !== query.model.provider ||\n typeof query.model.modelId !== \"string\" ||\n !query.model.modelId.trim() ||\n query.model.modelId.trim() !== query.model.modelId\n ) {\n addIssue(\n ctx,\n path,\n \"invalid_rerank_model\",\n \"Reranking requires an explicit provider and model ID.\"\n )\n }\n return { ...input, query: { ...query, model: { ...query.model }, input: input.query } }\n }\n case \"set\":\n return validateSet(query.inputs, query.op, path, ctx)\n case \"sort\": {\n const input = validateQueryNode(query.input, `${path}.input`, ctx)\n const fields = validateSortFields(\n query.fields,\n input.result,\n input.admissionState,\n \"sort\",\n path,\n ctx\n )\n return {\n result: input.result,\n query: { ...query, input: input.query, fields },\n admissionState: input.admissionState,\n }\n }\n case \"limit\": {\n const input = validateQueryNode(query.input, `${path}.input`, ctx)\n validateLimit(query.limit, path, ctx)\n return {\n result: input.result,\n query: { ...query, input: input.query },\n admissionState: input.admissionState,\n }\n }\n case \"page\": {\n const input = validateQueryNode(query.input, `${path}.input`, ctx)\n validatePage(query.pageSize, query.pageToken, path, ctx)\n return {\n result: input.result,\n query: { ...query, input: input.query },\n admissionState: input.admissionState,\n }\n }\n case \"project\": {\n const input = validateQueryNode(query.input, `${path}.input`, ctx)\n validateProjection(query.properties, input.result, input.admissionState, path, ctx)\n return {\n result: input.result,\n query: { ...query, input: input.query },\n admissionState: input.admissionState,\n }\n }\n case \"expand\": {\n const input = validateQueryNode(query.input, `${path}.input`, ctx)\n\n // Profiles are read for the rows a query returns. On a set operand they would have no row to\n // attach to, so only the outermost expand, where normalization puts it, may name them.\n const usersAllowed = path === \"$\"\n\n // expand is output-shaping: it attaches links without changing the matched\n // set, so the result type is the input's result type.\n const expansions = validateExpansions(\n query.expansions,\n input.result,\n input.admissionState,\n `${path}.expansions`,\n ctx,\n usersAllowed\n )\n validateUserExpansions(query.users, input.result, `${path}.users`, ctx, usersAllowed)\n validateUserExpansionsProjected(query.users, input.query, `${path}.users`, ctx)\n\n return {\n result: input.result,\n query: { ...query, input: input.query, expansions },\n admissionState: input.admissionState,\n }\n }\n }\n}\n\nfunction validateRefs(\n refs: readonly ObjectRef[],\n path: string,\n ctx: QueryValidationContext\n): QueryNodeValidation {\n if (refs.length === 0) {\n addIssue(ctx, `${path}.refs`, \"empty_refs\", \"refs must include at least one object reference\")\n }\n if (refs.length > ctx.maxRefs) {\n addIssue(\n ctx,\n `${path}.refs`,\n \"too_many_refs\",\n `refs must include at most ${ctx.maxRefs} object references`\n )\n }\n\n const objectTypeIds = new Set<string>()\n refs.forEach((ref, index) => {\n const refPath = `${path}.refs[${index}]`\n if (!ref.objectTypeId) {\n addIssue(ctx, `${refPath}.objectTypeId`, \"missing_object_type\", \"objectTypeId is required\")\n } else if (!ctx.ontology.getObjectTypeById(ref.objectTypeId)) {\n addIssue(\n ctx,\n `${refPath}.objectTypeId`,\n \"unknown_object_type\",\n formatUnknownObjectTypeMessage(ref.objectTypeId)\n )\n } else {\n objectTypeIds.add(ref.objectTypeId)\n }\n\n if (!ref.primaryId) {\n addIssue(ctx, `${refPath}.primaryId`, \"missing_primary_id\", \"primaryId is required\")\n }\n })\n\n return {\n result: { objectTypeIds: [...objectTypeIds] },\n query: { kind: \"refs\", refs: refs.map((ref) => ({ ...ref })) },\n }\n}\n\nfunction validateStart(\n objectTypeId: string,\n includeSubtypes: boolean | undefined,\n path: string,\n ctx: QueryValidationContext\n): QueryNodeValidation {\n if (!objectTypeId) {\n addIssue(ctx, path, \"missing_object_type\", \"start.objectTypeId is required\")\n return { result: { objectTypeIds: [] }, query: { kind: \"start\", objectTypeId } }\n }\n\n if (!ctx.ontology.getObjectTypeById(objectTypeId)) {\n addIssue(ctx, path, \"unknown_object_type\", formatUnknownObjectTypeMessage(objectTypeId))\n return { result: { objectTypeIds: [] }, query: { kind: \"start\", objectTypeId } }\n }\n\n const objectTypeIds = includeSubtypes ? withSubtypes([objectTypeId], ctx) : [objectTypeId]\n\n return { result: { objectTypeIds }, query: { kind: \"start\", objectTypeId, includeSubtypes } }\n}\n\nfunction validatePredicate(\n predicate: ObjectQueryPredicate,\n shape: ObjectQueryResultShape,\n admissionState: ObjectQueryAdmissionState,\n path: string,\n ctx: QueryValidationContext\n): ObjectQueryPredicate {\n switch (predicate.op) {\n case \"and\":\n case \"or\":\n if (predicate.items.length === 0) {\n addIssue(\n ctx,\n path,\n \"empty_predicate_group\",\n `Predicate '${predicate.op}' must not be empty`\n )\n }\n return {\n ...predicate,\n items: predicate.items.map((item, index) =>\n validatePredicate(item, shape, admissionState, `${path}.items[${index}]`, ctx)\n ),\n }\n case \"not\":\n return {\n ...predicate,\n item: validatePredicate(predicate.item, shape, admissionState, `${path}.item`, ctx),\n }\n case \"eq\":\n case \"neq\":\n case \"lt\":\n case \"lte\":\n case \"gt\":\n case \"gte\": {\n const { scalarKind: _authoredScalarKind, ...authoredPredicate } = predicate\n const scalarKind = resolveAndValidatePredicateProperty(\n predicate.propertyId,\n predicate.op,\n shape,\n path,\n ctx\n )\n validatePredicateValue(predicate.propertyId, predicate.op, predicate.value, shape, path, ctx)\n admitProperty(ctx, {\n state: admissionState,\n propertyId: predicate.propertyId,\n use: \"filter\",\n path,\n })\n return {\n ...authoredPredicate,\n value: normalizeObjectQueryValue(predicate.value, scalarKind),\n ...(scalarKind ? { scalarKind } : {}),\n }\n }\n case \"in\": {\n const { scalarKind: _authoredScalarKind, ...authoredPredicate } = predicate\n const scalarKind = resolveAndValidatePredicateProperty(\n predicate.propertyId,\n predicate.op,\n shape,\n path,\n ctx\n )\n if (predicate.values.length === 0) {\n addIssue(ctx, path, \"empty_in_values\", \"Predicate 'in' must include at least one value\")\n }\n predicate.values.forEach((value, index) => {\n validatePredicateValue(\n predicate.propertyId,\n predicate.op,\n value,\n shape,\n `${path}.values[${index}]`,\n ctx\n )\n })\n admitProperty(ctx, {\n state: admissionState,\n propertyId: predicate.propertyId,\n use: \"filter\",\n path,\n })\n return {\n ...authoredPredicate,\n values: predicate.values.map((value) => normalizeObjectQueryValue(value, scalarKind)),\n ...(scalarKind ? { scalarKind } : {}),\n }\n }\n case \"exists\":\n resolveAndValidatePredicateProperty(predicate.propertyId, predicate.op, shape, path, ctx)\n admitProperty(ctx, {\n state: admissionState,\n propertyId: predicate.propertyId,\n use: \"filter\",\n path,\n })\n if (typeof predicate.value !== \"boolean\") {\n addIssue(ctx, path, \"invalid_exists_value\", \"Predicate 'exists' value must be boolean\")\n }\n return predicate\n case \"constant\":\n if (typeof predicate.value !== \"boolean\") {\n addIssue(ctx, path, \"invalid_constant_value\", \"Predicate 'constant' value must be boolean\")\n }\n return predicate\n case \"contains\": {\n const { scalarKind: _authoredScalarKind, ...authoredPredicate } = predicate\n const scalarKind = resolveAndValidatePredicateProperty(\n predicate.propertyId,\n predicate.op,\n shape,\n path,\n ctx\n )\n validateContainsValue(predicate.propertyId, predicate.value, shape, path, ctx)\n admitProperty(ctx, {\n state: admissionState,\n propertyId: predicate.propertyId,\n use: \"filter\",\n path,\n })\n return {\n ...authoredPredicate,\n value: normalizeObjectQueryValue(predicate.value, scalarKind),\n ...(scalarKind ? { scalarKind } : {}),\n }\n }\n }\n}\n\nfunction resolveAndValidatePredicateProperty(\n propertyId: string,\n op: ObjectQueryPredicate[\"op\"],\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext\n): QueryScalarKind | undefined {\n const properties = getPropertiesForResult(propertyId, shape, path, ctx)\n if (properties.length === 0) return undefined\n const schemas: Schema[] = []\n\n for (const { objectType, property } of properties) {\n const schema = resolveSchemaForProperty(property, objectType.id, ctx, path)\n if (schema) schemas.push(schema)\n\n if (isPrimaryExactPredicate(property, op)) {\n continue\n }\n\n if (property.query?.searchable !== true || property.query.filterable !== true) {\n addIssue(\n ctx,\n path,\n \"property_not_filterable\",\n `Property '${propertyId}' on '${objectType.id}' must set query.searchable: true and query.filterable: true before it can be used in predicates`\n )\n continue\n }\n\n if (!schema) continue\n\n if ((op === \"lt\" || op === \"lte\" || op === \"gt\" || op === \"gte\") && !isSortableSchema(schema)) {\n addIssue(\n ctx,\n path,\n \"operator_not_supported_for_schema\",\n `Predicate '${op}' cannot be used with property '${propertyId}' on '${objectType.id}' because its schema is not orderable`\n )\n }\n\n if ((op === \"eq\" || op === \"neq\" || op === \"in\" || op === \"exists\") && !isExactSchema(schema)) {\n addIssue(\n ctx,\n path,\n \"operator_not_supported_for_schema\",\n `Predicate '${op}' cannot be used with property '${propertyId}' on '${objectType.id}' because its schema cannot be exact-matched`\n )\n }\n\n if (op === \"contains\" && !isContainsSchema(schema)) {\n addIssue(\n ctx,\n path,\n \"operator_not_supported_for_schema\",\n `Predicate 'contains' cannot be used with property '${propertyId}' on '${objectType.id}' because its schema is not string, array, or map`\n )\n }\n }\n\n if (op === \"exists\") return undefined\n if (op === \"contains\") return resolveArrayItemScalarKind(schemas, ctx)\n return resolveCommonQueryScalarKind(schemas, propertyId, path, ctx)\n}\n\n/**\n * Item scalar kind for `contains` over arrays, so array membership compares items the way `eq`\n * compares values. Strings and maps keep substring and key semantics, and mixed item kinds keep the\n * untyped comparison.\n */\nfunction resolveArrayItemScalarKind(\n schemas: readonly Schema[],\n ctx: QueryValidationContext\n): QueryScalarKind | undefined {\n const kinds = new Set<QueryScalarKind | undefined>()\n for (const schema of schemas) {\n if (typeof schema === \"string\" || schema.type !== \"array\") return undefined\n const items = resolveValueTypeRefs(schema.items, ctx.valueTypesById)\n kinds.add(items ? queryScalarKindForSchema(items) : undefined)\n }\n return kinds.size === 1 ? [...kinds][0] : undefined\n}\n\nfunction resolveValueTypeRefs(\n schema: Schema,\n valueTypesById: ReadonlyMap<string, ValueType>,\n seen = new Set<string>()\n): Schema | undefined {\n if (typeof schema === \"string\" || schema.type !== \"valueTypeRef\") return schema\n if (seen.has(schema.valueTypeId)) return undefined\n seen.add(schema.valueTypeId)\n const resolved = schema._resolved ?? valueTypesById.get(schema.valueTypeId)?.schema\n return resolved ? resolveValueTypeRefs(resolved, valueTypesById, seen) : undefined\n}\n\n/**\n * Write a compared value in the form storage writes it. Stores compare dates and timestamps as\n * their canonical text, so `…T02:00:00+02:00` and `…T00:00:00Z` only meet once both are canonical.\n * A value that does not normalize stays as authored: validation reports it.\n */\nfunction normalizeObjectQueryValue(value: unknown, scalarKind: QueryScalarKind | undefined) {\n try {\n if (scalarKind === \"decimal\" && typeof value === \"string\") return normalizeDecimalValue(value)\n if ((scalarKind === \"date\" || scalarKind === \"timestamp\") && isTemporalValue(value)) {\n return normalizeSchemaValue(scalarKind, value, \"predicate value\", NO_VALUE_TYPES)\n }\n } catch {\n return value\n }\n\n return value\n}\n\nconst NO_VALUE_TYPES: ReadonlyMap<string, ValueType> = new Map()\n\nfunction isTemporalValue(value: unknown): value is string | Date {\n return typeof value === \"string\" || value instanceof Date\n}\n\nfunction resolveCommonQueryScalarKind(\n schemas: readonly Schema[],\n propertyId: string,\n path: string,\n ctx: QueryValidationContext\n): QueryScalarKind | undefined {\n const scalarKinds = schemas.map(queryScalarKindForSchema)\n if (scalarKinds.length === 0 || scalarKinds.some((kind) => kind === undefined)) {\n return undefined\n }\n\n const resolvedKinds = new Set(scalarKinds)\n if (resolvedKinds.size === 1) return scalarKinds[0]\n\n addIssue(\n ctx,\n path,\n \"incompatible_property_scalar_kinds\",\n `Property '${propertyId}' resolves to incompatible scalar schemas: ${[...resolvedKinds].join(\n \", \"\n )}`\n )\n return undefined\n}\n\nfunction validatePredicateValue(\n propertyId: string,\n op: ObjectQueryPredicate[\"op\"],\n value: unknown,\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext\n): void {\n if (isCurrentUser(value)) {\n validateCurrentUserPredicate(propertyId, op, shape, path, ctx)\n return\n }\n\n for (const { objectType, property } of getPropertiesForResult(propertyId, shape, path, ctx, {\n reportMissing: false,\n })) {\n try {\n validatePropertyValue(property, value, `${objectType.id}.${property.id}`, ctx.valueTypesById)\n } catch (error) {\n addIssue(\n ctx,\n path,\n \"invalid_predicate_value\",\n error instanceof Error\n ? error.message\n : `Invalid value for property '${property.id}' on '${objectType.id}'`\n )\n }\n }\n}\n\nfunction validateContainsValue(\n propertyId: string,\n value: unknown,\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext\n): void {\n if (isCurrentUser(value)) {\n validateCurrentUserPredicate(propertyId, \"contains\", shape, path, ctx)\n return\n }\n\n for (const { objectType, property } of getPropertiesForResult(propertyId, shape, path, ctx, {\n reportMissing: false,\n })) {\n const schema = resolveSchemaForProperty(property, objectType.id, ctx, path)\n if (!schema) continue\n\n if (typeof schema === \"string\") {\n if (isContainsSchema(schema)) {\n if (typeof value !== \"string\") {\n addIssue(\n ctx,\n path,\n \"invalid_contains_value\",\n `Predicate 'contains' value for '${objectType.id}.${property.id}' must be a string`\n )\n }\n }\n continue\n }\n\n if (schema.type === \"array\") {\n try {\n validateSchemaValue(\n schema.items,\n value,\n `${objectType.id}.${property.id}[]`,\n ctx.valueTypesById\n )\n } catch (error) {\n addIssue(\n ctx,\n path,\n \"invalid_contains_value\",\n error instanceof Error\n ? error.message\n : `Invalid contains value for '${objectType.id}.${property.id}'`\n )\n }\n continue\n }\n\n if (schema.type === \"map\" && typeof value !== \"string\") {\n addIssue(\n ctx,\n path,\n \"invalid_contains_value\",\n `Predicate 'contains' value for '${objectType.id}.${property.id}' must be a map key string`\n )\n }\n }\n}\n\n/**\n * `currentUser()` stands for a user reference: the executor replaces it with the reader's after\n * validation, so it compares only where a user reference does. `eq`, `neq` and `in` take it on a\n * `ref.user()` property, `contains` on a list of them.\n */\nfunction validateCurrentUserPredicate(\n propertyId: string,\n op: ObjectQueryPredicate[\"op\"],\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext\n): void {\n if (op !== \"eq\" && op !== \"neq\" && op !== \"in\" && op !== \"contains\") {\n addIssue(\n ctx,\n path,\n \"current_user_operator_not_supported\",\n `Predicate '${op}' cannot compare currentUser(); use eq, neq, in, or contains.`\n )\n return\n }\n\n for (const { objectType, property } of getPropertiesForResult(propertyId, shape, path, ctx, {\n reportMissing: false,\n })) {\n if (holdsUserReferences(property.schema, op === \"contains\", ctx)) continue\n\n addIssue(\n ctx,\n path,\n \"current_user_requires_user_reference\",\n op === \"contains\"\n ? `currentUser() can only be found in a list of ref.user() values; '${objectType.id}.${property.id}' is not one.`\n : `currentUser() can only be compared with a ref.user() property; '${objectType.id}.${property.id}' is not one.`\n )\n }\n}\n\n/** Whether the schema is a user reference or, for `contains`, a list of them. */\nfunction holdsUserReferences(schema: Schema, list: boolean, ctx: QueryValidationContext): boolean {\n const resolved = resolveValueTypeRefs(schema, ctx.valueTypesById)\n if (!list) return resolved === \"userRef\"\n\n if (typeof resolved !== \"object\" || resolved.type !== \"array\") return false\n return resolveValueTypeRefs(resolved.items, ctx.valueTypesById) === \"userRef\"\n}\n\nfunction validateTextQuery(\n query: string,\n fields: readonly string[] | undefined,\n shape: ObjectQueryResultShape,\n admissionState: ObjectQueryAdmissionState,\n path: string,\n ctx: QueryValidationContext\n): TextFieldResolution {\n if (query.trim().length === 0) {\n addIssue(ctx, path, \"empty_text_query\", \"Text query must not be empty\")\n }\n\n const fieldsByObjectType: Record<string, string[]> | undefined = fields ? undefined : {}\n\n for (const objectType of getObjectTypesForResult(shape, ctx)) {\n const fieldIds = fields ?? objectType.search?.defaultText\n if (!fieldIds || fieldIds.length === 0) {\n addIssue(\n ctx,\n path,\n \"missing_text_fields\",\n `Object type '${objectType.id}' must define search.defaultText or the text query must specify fields`\n )\n continue\n }\n\n const admitted = admitTextFields(fieldIds, fields === undefined, {\n state: admissionState,\n objectTypeId: objectType.id,\n path: `${path}.fields`,\n ctx,\n })\n if (fieldsByObjectType) fieldsByObjectType[objectType.id] = uniqueStrings(admitted)\n\n for (const fieldId of fieldIds) {\n const property = getProperty(objectType, fieldId)\n if (!property) {\n addIssue(\n ctx,\n path,\n \"unknown_text_field\",\n `Text query references unknown property '${fieldId}' on '${objectType.id}'`\n )\n continue\n }\n\n assertStaticSearchProperty(objectType.id, property, \"text query\", path, ctx)\n assertQueryFlag(objectType.id, property, \"text\", \"text query\", path, ctx)\n const schema = resolveSchemaForProperty(property, objectType.id, ctx, path)\n if (schema && !isTextSchema(schema)) {\n addIssue(\n ctx,\n path,\n \"text_field_not_string_like\",\n `Text query field '${fieldId}' on '${objectType.id}' must be string-like`\n )\n }\n }\n }\n\n return fieldsByObjectType ? { fieldsByObjectType } : {}\n}\n\n/**\n * Admit the fields a text query searches. Every explicit field must be admitted. Default fields\n * come from the type's search profile, so a reader that cannot use one searches the others\n * instead; only a type left with no usable default field is denied.\n */\nfunction admitTextFields(\n fieldIds: readonly string[],\n defaults: boolean,\n input: {\n readonly state: ObjectQueryAdmissionState\n readonly objectTypeId: string\n readonly path: string\n readonly ctx: QueryValidationContext\n }\n): readonly string[] {\n const admitted: string[] = []\n let firstDenial: Error | undefined\n for (const fieldId of fieldIds) {\n const denial = input.ctx.admission.property({\n state: input.state,\n propertyId: fieldId,\n objectTypeId: input.objectTypeId,\n use: \"text\",\n path: input.path,\n })\n if (!denial) {\n admitted.push(fieldId)\n } else if (!defaults) {\n recordAdmissionDenial(input.ctx, denial)\n } else {\n firstDenial ??= denial\n }\n }\n if (admitted.length === 0 && firstDenial) recordAdmissionDenial(input.ctx, firstDenial)\n return admitted\n}\n\nfunction validateVectorProfileQuery(\n query: ObjectQueryVector,\n shape: ObjectQueryResultShape,\n state: ObjectQueryAdmissionState,\n path: string,\n ctx: QueryValidationContext\n): ObjectQueryVector {\n const types = getObjectTypesForResult(shape, ctx)\n if (\n types.length !== 1 ||\n !Number.isSafeInteger(query.k) ||\n query.k < 1 ||\n query.k > MAX_VECTOR_K\n ) {\n addIssue(\n ctx,\n path,\n \"invalid_vector_profile_query\",\n `Vector search requires one type, one profile and k between 1 and ${MAX_VECTOR_K}`\n )\n return query\n }\n const objectType = types[0]!\n const profile =\n query.profile === undefined ? undefined : objectType.search?.vectors?.[query.profile]\n if (!profile) {\n addIssue(ctx, path, \"unknown_vector_profile\", `Unknown vector profile: ${query.profile}`)\n return query\n }\n for (const propertyId of profile.source)\n admitProperty(ctx, { state, propertyId, objectTypeId: objectType.id, use: \"vector\", path })\n let values = query.vector\n try {\n if (typeof values === \"string\") {\n if (!values.trim() || values.length > 8000) {\n throw new Error(\"Vector search text must be nonempty and at most 8000 characters.\")\n }\n } else {\n values = normalizeVector(values, profile.model.definition.dimensions)\n }\n } catch (error) {\n addIssue(ctx, path, \"invalid_vector\", error instanceof Error ? error.message : \"Invalid vector\")\n }\n return {\n ...query,\n vector: values,\n source: [...profile.source],\n configuration: vectorConfiguration(profile),\n }\n}\n\nfunction validateTraverse(\n linkId: string,\n direction: \"outgoing\" | \"incoming\",\n sourceObjectTypeId: string | undefined,\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext\n): ObjectQueryResultShape {\n if (!linkId) {\n addIssue(ctx, path, \"missing_link_id\", \"traverse.linkId is required\")\n return { objectTypeIds: [] }\n }\n\n if (direction === \"outgoing\") {\n if (sourceObjectTypeId !== undefined) {\n addIssue(\n ctx,\n path,\n \"traverse_source_not_applicable\",\n \"traverse.sourceObjectTypeId only applies to incoming traversal\"\n )\n }\n return validateOutgoingTraverse(linkId, shape, path, ctx)\n }\n\n return validateIncomingTraverse(linkId, sourceObjectTypeId, shape, path, ctx)\n}\n\nfunction validateOutgoingTraverse(\n linkId: string,\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext\n): ObjectQueryResultShape {\n const targetTypeIds: string[] = []\n\n for (const objectType of getObjectTypesForResult(shape, ctx)) {\n const link = objectType.links.find((candidate) => candidate.id === linkId)\n if (!link) {\n addIssue(\n ctx,\n path,\n \"unknown_link\",\n `Outgoing traversal references unknown link '${linkId}' on '${objectType.id}'`\n )\n continue\n }\n\n if (link.targetObjectTypeId === \"*\") {\n addIssue(\n ctx,\n path,\n \"wildcard_traverse_target\",\n `Outgoing traversal over wildcard link '${objectType.id}.${linkId}' cannot infer a target object type`\n )\n continue\n }\n\n const declaredTargets = Array.isArray(link.targetObjectTypeId)\n ? link.targetObjectTypeId\n : [link.targetObjectTypeId]\n\n for (const targetId of declaredTargets) {\n if (!ctx.ontology.getObjectTypeById(targetId)) {\n addIssue(\n ctx,\n path,\n \"unknown_link_target\",\n `Outgoing traversal over '${objectType.id}.${linkId}' targets unknown object type '${targetId}'`\n )\n } else {\n targetTypeIds.push(targetId)\n }\n }\n }\n\n const objectTypeIds = uniqueStrings(targetTypeIds)\n touchLinkTargets(objectTypeIds, ctx)\n return { objectTypeIds }\n}\n\nfunction validateIncomingTraverse(\n linkId: string,\n sourceObjectTypeId: string | undefined,\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext\n): ObjectQueryResultShape {\n let candidateTypes = ctx.ontology.listObjectTypes()\n if (sourceObjectTypeId !== undefined) {\n const sourceType = ctx.ontology.getObjectTypeById(sourceObjectTypeId)\n if (!sourceType) {\n addIssue(\n ctx,\n path,\n \"unknown_traverse_source\",\n `Incoming traversal references unknown source object type '${sourceObjectTypeId}'`\n )\n return { objectTypeIds: [] }\n }\n candidateTypes = [sourceType]\n }\n\n const sourceTypeIds: string[] = []\n\n for (const sourceType of candidateTypes) {\n const link = sourceType.links.find((candidate) => candidate.id === linkId)\n if (!link) continue\n\n if (link.targetObjectTypeId === \"*\") {\n sourceTypeIds.push(sourceType.id)\n continue\n }\n\n const matches = shape.objectTypeIds.some((targetTypeId) =>\n ctx.ontology.isValidLinkTarget(link.targetObjectTypeId, targetTypeId)\n )\n if (matches) sourceTypeIds.push(sourceType.id)\n }\n\n if (sourceTypeIds.length === 0) {\n addIssue(\n ctx,\n path,\n \"incoming_link_not_found\",\n `Incoming traversal found no source object types with link '${linkId}' targeting ${shape.objectTypeIds.join(\n \" | \"\n )}`\n )\n }\n\n return { objectTypeIds: uniqueStrings(sourceTypeIds) }\n}\n\nfunction validateExpansions(\n expansions: readonly ObjectExpansion[],\n shape: ObjectQueryResultShape,\n admissionState: ObjectQueryAdmissionState,\n path: string,\n ctx: QueryValidationContext,\n usersAllowed: boolean\n): ObjectExpansion[] {\n return expansions.map((expansion, index) =>\n validateExpansion(expansion, shape, admissionState, `${path}[${index}]`, ctx, usersAllowed)\n )\n}\n\nfunction validateExpansion(\n expansion: ObjectExpansion,\n shape: ObjectQueryResultShape,\n admissionState: ObjectQueryAdmissionState,\n path: string,\n ctx: QueryValidationContext,\n usersAllowed: boolean\n): ObjectExpansion {\n if (!expansion.linkId) {\n addIssue(ctx, path, \"missing_expand_link\", \"expand.linkId is required\")\n return expansion\n }\n\n const targetShape =\n expansion.direction === \"incoming\"\n ? resolveIncomingExpansionTargets(\n expansion.linkId,\n expansion.sourceObjectTypeId,\n shape,\n path,\n ctx\n )\n : resolveOutgoingExpansionTargets(\n expansion.linkId,\n expansion.sourceObjectTypeId,\n shape,\n path,\n ctx\n )\n const targetAdmissionState = admitTransition(\n ctx,\n ctx.admission.edge({\n state: admissionState,\n result: targetShape,\n linkId: expansion.linkId,\n direction: expansion.direction,\n sourceObjectTypeId: expansion.sourceObjectTypeId,\n use: \"expand\",\n path,\n })\n )\n\n // Expansion targets are touched types: the principal must be able to `view`\n // every type a query hydrates, exactly like `start`/`traverse`. `dispatch`'s\n // automatic fold only covers result types, and expansion targets are not in\n // the result — so add them here (recursively, via the nested call below).\n for (const targetTypeId of targetShape.objectTypeIds) {\n ctx.touchedObjectTypeIds.add(targetTypeId)\n }\n\n validateExpansionLimit(expansion.limit, path, ctx)\n const orderBy = expansion.orderBy\n ? validateSortFields(\n expansion.orderBy,\n targetShape,\n targetAdmissionState,\n \"expand.orderBy\",\n `${path}.orderBy`,\n ctx\n )\n : undefined\n const expand = expansion.expand\n ? validateExpansions(\n expansion.expand,\n targetShape,\n targetAdmissionState,\n `${path}.expand`,\n ctx,\n usersAllowed\n )\n : undefined\n validateUserExpansions(expansion.users, targetShape, `${path}.users`, ctx, usersAllowed)\n\n return { ...expansion, orderBy, expand }\n}\n\n/**\n * Each expanded user property must be a `ref.user()` property, or an array of them, on at least\n * one type of the shape, like an expanded link. Telemetry cannot hold user references.\n *\n * No admission sees it: a profile is never returned to a delegated reader, and a marked value the\n * reader cannot read is removed before its profile would be looked up.\n *\n * `usersAllowed` is false under any expand but the outermost one, at every depth.\n */\nfunction validateUserExpansions(\n users: readonly string[] | undefined,\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext,\n usersAllowed: boolean\n): void {\n if (users === undefined) return\n\n if (!Array.isArray(users)) {\n addIssue(ctx, path, \"invalid_user_expansion\", \"expand.users must be an array of property ids\")\n return\n }\n\n if (!usersAllowed && users.length > 0) {\n addIssue(\n ctx,\n path,\n \"invalid_user_expansion\",\n \"Only the outermost expand can expand user properties; a set operand cannot.\"\n )\n return\n }\n\n users.forEach((propertyId, index) => {\n const propertyPath = `${path}[${index}]`\n\n if (typeof propertyId !== \"string\" || propertyId.length === 0) {\n addIssue(ctx, propertyPath, \"invalid_user_expansion\", \"expand.users ids must not be empty\")\n return\n }\n\n const declared = getPropertiesForResult(propertyId, shape, propertyPath, ctx, {\n reportMissing: false,\n })\n if (declared.length === 0) {\n addIssue(\n ctx,\n propertyPath,\n \"unknown_property\",\n `Expansion references property '${propertyId}' not present on result type ${shape.objectTypeIds.join(\n \" | \"\n )} (an expand abandoned by a later traverse?)`\n )\n return\n }\n\n for (const { objectType, property } of declared) {\n if (isUserRefPropertySchema(property.schema)) continue\n addIssue(\n ctx,\n propertyPath,\n \"invalid_user_expansion\",\n `Property '${propertyId}' on '${objectType.id}' is not a ref.user() property; expand() takes a link or a user property.`\n )\n }\n })\n}\n\n/**\n * A projection that leaves out an expanded user property would make its profile read as \"no\n * user\". Refuse it instead.\n */\nfunction validateUserExpansionsProjected(\n users: readonly string[] | undefined,\n input: ObjectQuery,\n path: string,\n ctx: QueryValidationContext\n): void {\n if (!Array.isArray(users)) return\n\n const projected = projectedProperties(input)\n if (projected === undefined) return\n\n users.forEach((propertyId, index) => {\n if (projected.includes(propertyId)) return\n addIssue(\n ctx,\n `${path}[${index}]`,\n \"invalid_user_expansion\",\n `Expanded user property '${propertyId}' must be projected too.`\n )\n })\n}\n\n/**\n * The properties a row keeps, from the projections below the expand on the same result type, or\n * `undefined` when every property is kept. A set keeps only what each operand keeps.\n */\nfunction projectedProperties(query: ObjectQuery): readonly string[] | undefined {\n switch (query.kind) {\n case \"project\":\n return query.properties\n case \"set\":\n return keptByEveryOperand(query.inputs.map(projectedProperties))\n case \"filter\":\n case \"text\":\n case \"vector\":\n case \"rerank\":\n case \"sort\":\n case \"limit\":\n case \"page\":\n return projectedProperties(query.input)\n default:\n return undefined\n }\n}\n\n// An operand without a projection keeps every property, so it narrows nothing.\nfunction keptByEveryOperand(\n projections: readonly (readonly string[] | undefined)[]\n): readonly string[] | undefined {\n const projected = projections.filter((properties) => properties !== undefined)\n if (projected.length === 0) return undefined\n\n return projected.reduce((kept, properties) =>\n kept.filter((propertyId) => properties.includes(propertyId))\n )\n}\n\nfunction resolveOutgoingExpansionTargets(\n linkId: string,\n sourceObjectTypeId: string | undefined,\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext\n): ObjectQueryResultShape {\n if (sourceObjectTypeId !== undefined) {\n addIssue(\n ctx,\n path,\n \"expand_source_not_applicable\",\n \"expand.sourceObjectTypeId only applies to incoming expansion\"\n )\n }\n\n const targetTypeIds: string[] = []\n let foundOnAnyType = false\n\n for (const objectType of getObjectTypesForResult(shape, ctx)) {\n const link = objectType.links.find((candidate) => candidate.id === linkId)\n if (!link) continue\n foundOnAnyType = true\n\n if (link.targetObjectTypeId === \"*\") {\n addIssue(\n ctx,\n path,\n \"wildcard_expand_target\",\n `Expansion over wildcard link '${objectType.id}.${linkId}' cannot infer a target object type`\n )\n continue\n }\n\n const declaredTargets = Array.isArray(link.targetObjectTypeId)\n ? link.targetObjectTypeId\n : [link.targetObjectTypeId]\n\n for (const targetId of declaredTargets) {\n if (!ctx.ontology.getObjectTypeById(targetId)) {\n addIssue(\n ctx,\n path,\n \"unknown_expand_target\",\n `Expansion over '${objectType.id}.${linkId}' targets unknown object type '${targetId}'`\n )\n } else {\n targetTypeIds.push(targetId)\n }\n }\n }\n\n // A link absent from every result type is the \"abandoned by a later traverse\"\n // case: expands hoist above traverse, so an expand on a type the traverse\n // replaced cannot resolve its link on the final result type.\n if (!foundOnAnyType) {\n addIssue(\n ctx,\n path,\n \"unknown_expand_link\",\n `Expansion references link '${linkId}' not present on result type ${shape.objectTypeIds.join(\n \" | \"\n )} (an expand abandoned by a later traverse?)`\n )\n }\n\n const objectTypeIds = uniqueStrings(targetTypeIds)\n touchLinkTargets(objectTypeIds, ctx)\n return { objectTypeIds }\n}\n\n/**\n * Following a link outgoing reads every subtype of its declared targets: links accept subtype\n * targets and storage follows them by link id alone. Authorize those reads like a `start` that\n * includes subtypes; the result shape keeps the declared targets that later nodes validate against.\n * Incoming edges already name every source type they can return: storage matches a pinned\n * `sourceObjectTypeId` exactly, and otherwise subtypes inherit the link.\n */\nfunction touchLinkTargets(objectTypeIds: readonly string[], ctx: QueryValidationContext): void {\n for (const objectTypeId of withSubtypes(objectTypeIds, ctx)) {\n ctx.touchedObjectTypeIds.add(objectTypeId)\n }\n}\n\nfunction resolveIncomingExpansionTargets(\n linkId: string,\n sourceObjectTypeId: string | undefined,\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext\n): ObjectQueryResultShape {\n let candidateTypes = ctx.ontology.listObjectTypes()\n if (sourceObjectTypeId !== undefined) {\n const sourceType = ctx.ontology.getObjectTypeById(sourceObjectTypeId)\n if (!sourceType) {\n addIssue(\n ctx,\n path,\n \"unknown_expand_source\",\n `Incoming expansion references unknown source object type '${sourceObjectTypeId}'`\n )\n return { objectTypeIds: [] }\n }\n candidateTypes = [sourceType]\n }\n\n const sourceTypeIds: string[] = []\n\n for (const sourceType of candidateTypes) {\n const link = sourceType.links.find((candidate) => candidate.id === linkId)\n if (!link) continue\n\n if (link.targetObjectTypeId === \"*\") {\n sourceTypeIds.push(sourceType.id)\n continue\n }\n\n const matches = shape.objectTypeIds.some((targetTypeId) =>\n ctx.ontology.isValidLinkTarget(link.targetObjectTypeId, targetTypeId)\n )\n if (matches) sourceTypeIds.push(sourceType.id)\n }\n\n if (sourceTypeIds.length === 0) {\n addIssue(\n ctx,\n path,\n \"incoming_expand_link_not_found\",\n `Incoming expansion found no source object types with link '${linkId}' targeting ${shape.objectTypeIds.join(\n \" | \"\n )}`\n )\n }\n\n return { objectTypeIds: uniqueStrings(sourceTypeIds) }\n}\n\nfunction validateExpansionLimit(\n limit: number | undefined,\n path: string,\n ctx: QueryValidationContext\n): void {\n if (limit === undefined) return\n if (!Number.isInteger(limit) || limit < 0) {\n addIssue(\n ctx,\n `${path}.limit`,\n \"invalid_expand_limit\",\n \"expand.limit must be a non-negative integer\"\n )\n }\n}\n\nfunction validateSet(\n inputs: readonly ObjectQuery[],\n op: \"union\" | \"intersect\" | \"subtract\",\n path: string,\n ctx: QueryValidationContext\n): QueryValidationResult {\n if (inputs.length === 0) {\n addIssue(ctx, path, \"empty_set\", `Set operation '${op}' must include at least one input`)\n return {\n result: { objectTypeIds: [] },\n query: { kind: \"set\", op, inputs },\n admissionState: ctx.admission.empty(),\n }\n }\n\n const results = inputs.map((input, index) =>\n validateQueryNode(input, `${path}.inputs[${index}]`, ctx)\n )\n const first = results[0]?.result ?? { objectTypeIds: [] }\n const expected = keyForTypeIds(first.objectTypeIds)\n\n results.forEach((result, index) => {\n if (keyForTypeIds(result.result.objectTypeIds) !== expected) {\n addIssue(\n ctx,\n `${path}.inputs[${index}]`,\n \"incompatible_set_input\",\n `Set operation '${op}' inputs must produce the same object type set`\n )\n }\n })\n\n return {\n result: first,\n query: { kind: \"set\", op, inputs: results.map((result) => result.query) },\n admissionState: ctx.admission.set({\n op,\n states: results.map((result) => result.admissionState),\n path,\n }),\n }\n}\n\nfunction validateSortFields(\n fields: readonly ObjectQuerySortField[],\n shape: ObjectQueryResultShape,\n admissionState: ObjectQueryAdmissionState,\n use: Extract<ObjectQueryPropertyUse, \"sort\" | \"expand.orderBy\">,\n path: string,\n ctx: QueryValidationContext\n): ObjectQuerySortField[] {\n if (fields.length === 0) {\n addIssue(ctx, path, \"empty_sort\", \"Sort must include at least one field\")\n return []\n }\n\n const seen = new Set<string>()\n return fields.map((field, index) => {\n if (field.direction && field.direction !== \"asc\" && field.direction !== \"desc\") {\n addIssue(\n ctx,\n `${path}.fields[${index}]`,\n \"invalid_sort_direction\",\n \"Sort direction must be asc or desc\"\n )\n }\n\n const key = field.kind === \"property\" ? `property:${field.propertyId}` : \"relevance\"\n if (seen.has(key)) {\n addIssue(\n ctx,\n `${path}.fields[${index}]`,\n \"duplicate_sort_field\",\n `Duplicate sort field '${key}'`\n )\n }\n seen.add(key)\n\n if (field.kind === \"relevance\") return field\n\n admitProperty(ctx, {\n state: admissionState,\n propertyId: field.propertyId,\n use,\n path: `${path}.fields[${index}]`,\n })\n\n const { scalarKind: _authoredScalarKind, ...authoredField } = field\n\n const schemas: Schema[] = []\n\n for (const { objectType, property } of getPropertiesForResult(\n field.propertyId,\n shape,\n `${path}.fields[${index}]`,\n ctx\n )) {\n if (property.query?.searchable !== true || property.query.sortable !== true) {\n addIssue(\n ctx,\n `${path}.fields[${index}]`,\n \"property_not_sortable\",\n `Property '${property.id}' on '${objectType.id}' must set query.searchable: true and query.sortable: true before it can be sorted`\n )\n continue\n }\n\n const schema = resolveSchemaForProperty(\n property,\n objectType.id,\n ctx,\n `${path}.fields[${index}]`\n )\n if (schema) schemas.push(schema)\n if (schema && !isSortableSchema(schema)) {\n addIssue(\n ctx,\n `${path}.fields[${index}]`,\n \"sort_field_not_orderable\",\n `Sort field '${property.id}' on '${objectType.id}' is not orderable`\n )\n }\n }\n\n const scalarKind = resolveCommonQueryScalarKind(\n schemas,\n field.propertyId,\n `${path}.fields[${index}]`,\n ctx\n )\n return { ...authoredField, ...(scalarKind ? { scalarKind } : {}) }\n })\n}\n\nfunction validateLimit(limit: number, path: string, ctx: QueryValidationContext): void {\n if (!Number.isInteger(limit) || limit < 0) {\n addIssue(ctx, path, \"invalid_limit\", \"limit must be a non-negative integer\")\n } else if (limit > ctx.maxLimit) {\n addIssue(ctx, path, \"limit_too_large\", `limit must be <= ${ctx.maxLimit}`)\n }\n}\n\nfunction validatePage(\n pageSize: number,\n pageToken: string | undefined,\n path: string,\n ctx: QueryValidationContext\n): void {\n if (!Number.isInteger(pageSize) || pageSize <= 0) {\n addIssue(ctx, path, \"invalid_page_size\", \"pageSize must be a positive integer\")\n } else if (pageSize > ctx.maxPageSize) {\n addIssue(ctx, path, \"page_size_too_large\", `pageSize must be <= ${ctx.maxPageSize}`)\n }\n\n if (pageToken !== undefined && pageToken.length === 0) {\n addIssue(ctx, path, \"empty_page_token\", \"pageToken must not be empty when provided\")\n }\n}\n\nfunction validateProjection(\n properties: readonly string[] | undefined,\n shape: ObjectQueryResultShape,\n admissionState: ObjectQueryAdmissionState,\n path: string,\n ctx: QueryValidationContext\n): void {\n if (!properties) return\n if (properties.length === 0) {\n addIssue(ctx, path, \"empty_projection\", \"project.properties must not be empty when provided\")\n }\n\n const seen = new Set<string>()\n properties.forEach((propertyId, index) => {\n admitProperty(ctx, {\n state: admissionState,\n propertyId,\n use: \"project\",\n path: `${path}.properties[${index}]`,\n })\n if (seen.has(propertyId)) {\n addIssue(\n ctx,\n `${path}.properties[${index}]`,\n \"duplicate_projection_property\",\n `Duplicate projected property '${propertyId}'`\n )\n }\n seen.add(propertyId)\n getPropertiesForResult(propertyId, shape, `${path}.properties[${index}]`, ctx)\n })\n}\n\nfunction getObjectTypesForResult(\n shape: ObjectQueryResultShape,\n ctx: QueryValidationContext\n): ObjectType[] {\n const objectTypes: ObjectType[] = []\n for (const objectTypeId of shape.objectTypeIds) {\n const objectType = ctx.ontology.getObjectTypeById(objectTypeId)\n if (objectType) objectTypes.push(objectType)\n }\n return objectTypes\n}\n\nfunction getPropertiesForResult(\n propertyId: string,\n shape: ObjectQueryResultShape,\n path: string,\n ctx: QueryValidationContext,\n options: { reportMissing?: boolean } = {}\n): { objectType: ObjectType; property: Property }[] {\n const results: { objectType: ObjectType; property: Property }[] = []\n\n for (const objectType of getObjectTypesForResult(shape, ctx)) {\n const property = getProperty(objectType, propertyId)\n if (!property) {\n if (options.reportMissing === false) {\n continue\n }\n addIssue(\n ctx,\n path,\n \"unknown_property\",\n `Property '${propertyId}' does not exist on object type '${objectType.id}'`\n )\n continue\n }\n results.push({ objectType, property })\n }\n\n return results\n}\n\nfunction getProperty(objectType: ObjectType, propertyId: string): Property | undefined {\n return objectType.properties.find((property) => property.id === propertyId)\n}\n\nfunction assertStaticSearchProperty(\n objectTypeId: string,\n property: Property,\n context: string,\n path: string,\n ctx: QueryValidationContext\n): void {\n if (property.mode === \"telemetry\") {\n addIssue(\n ctx,\n path,\n \"telemetry_search_property\",\n `${context} references telemetry property '${property.id}' on '${objectTypeId}'. Search can only reference static properties because telemetry latest values are not object-query indexed.`\n )\n }\n}\n\nfunction assertQueryFlag(\n objectTypeId: string,\n property: Property,\n flag: \"text\",\n context: string,\n path: string,\n ctx: QueryValidationContext\n): void {\n if (property.query?.searchable === true && property.query[flag] === true) return\n addIssue(\n ctx,\n path,\n \"query_field_not_enabled\",\n `${context} field '${property.id}' on '${objectTypeId}' must set query.searchable: true and query.${flag}: true`\n )\n}\n\nfunction resolveSchemaForProperty(\n property: Property,\n objectTypeId: string,\n ctx: QueryValidationContext,\n path: string\n): Schema | null {\n try {\n return resolveSchema(property.schema, ctx.valueTypesById)\n } catch (error) {\n addIssue(\n ctx,\n path,\n \"unresolved_property_schema\",\n error instanceof Error\n ? error.message\n : `Could not resolve schema for '${objectTypeId}.${property.id}'`\n )\n return null\n }\n}\n\nfunction resolveSchema(\n schema: Schema,\n valueTypesById: ReadonlyMap<string, ValueType>,\n seenValueTypeIds = new Set<string>()\n): Schema {\n if (typeof schema === \"string\") return schema\n if (schema.type !== \"valueTypeRef\") return schema\n if (seenValueTypeIds.has(schema.valueTypeId)) {\n throw new Error(`Circular valueTypeRef '${schema.valueTypeId}'`)\n }\n\n const resolved = schema._resolved ?? valueTypesById.get(schema.valueTypeId)?.schema\n if (!resolved) {\n throw new Error(`Unknown valueTypeRef '${schema.valueTypeId}'`)\n }\n\n seenValueTypeIds.add(schema.valueTypeId)\n return resolveSchema(resolved, valueTypesById, seenValueTypeIds)\n}\n\nfunction isPrimaryExactPredicate(property: Property, op: ObjectQueryPredicate[\"op\"]): boolean {\n return property.primary === true && (op === \"eq\" || op === \"in\")\n}\n\nfunction keyForTypeIds(typeIds: readonly string[]): string {\n return uniqueStrings(typeIds).sort().join(\"\\0\")\n}\n\nfunction uniqueStrings(values: readonly string[]): string[] {\n return [...new Set(values)]\n}\n\nfunction withSubtypes(objectTypeIds: readonly string[], ctx: QueryValidationContext): string[] {\n return uniqueStrings(objectTypeIds.flatMap((id) => [id, ...ctx.ontology.listSubTypes(id)]))\n}\n\nfunction admitTransition(\n ctx: QueryValidationContext,\n transition: ObjectQueryAdmissionTransition\n): ObjectQueryAdmissionState {\n if (transition.denial) recordAdmissionDenial(ctx, transition.denial)\n return transition.state\n}\n\nfunction admitProperty(\n ctx: QueryValidationContext,\n input: Parameters<ObjectQuerySemanticAdmission[\"property\"]>[0]\n): void {\n const denial = ctx.admission.property(input)\n if (denial) recordAdmissionDenial(ctx, denial)\n}\n\nfunction recordAdmissionDenial(ctx: QueryValidationContext, denial: Error): void {\n // Only the first deterministic denial is observable. Keep walking so ordinary validation keeps\n // priority, but do not retain attacker-controlled messages for every rejected field or edge.\n if (ctx.admissionDenials.length === 0) ctx.admissionDenials.push(denial)\n}\n\nfunction addIssue(ctx: QueryValidationContext, path: string, code: string, message: string): void {\n ctx.issues.push({ path, code, message })\n}\n",
|
|
21
|
+
"import { bindCurrentUserPredicate } from \"../objects/query/current-user\"\nimport { ObjectQueryValidationError } from \"../objects/query/errors\"\nimport type { ObjectQueryPredicate } from \"../objects/query/ir\"\nimport {\n type ObjectQuerySemanticAdmission,\n validateObjectQueryWithAdmission,\n} from \"../objects/query/validate\"\nimport type { OntologyRegistry } from \"../ontology\"\nimport { compileConditionalObjectReadScope } from \"../storage/objects/read-scope\"\nimport type { ObjectReadScopeFactory } from \"../storage/objects/types\"\nimport { SecurityValidationError } from \"./errors\"\nimport type { GrantDefinition, Selection } from \"./types\"\n\n/** A role's `can.view(Type).where(...)`, validated against the ontology at startup. */\nexport interface ViewCondition {\n readonly roleId: string\n /** The type the grant names. The condition also applies to its subtypes. */\n readonly objectTypeId: string\n /**\n * The condition as the validator returns it, `scalarKind` resolved, and deeply frozen. It may\n * still hold `currentUser()`, which each reader binds to its own user.\n */\n readonly predicate: ObjectQueryPredicate\n}\n\n/**\n * Validate a role grant's condition at startup: `can.view(Type).where(...)`.\n *\n * The condition is validated as a filter over the type and every subtype the grant covers, which\n * is the query its reads run. Without an ontology there is nothing to validate it against, so it\n * is refused.\n */\nexport function resolveViewCondition(\n roleId: string,\n grant: GrantDefinition,\n ontology: OntologyRegistry | undefined\n): ViewCondition | undefined {\n if (!(\"condition\" in grant) || grant.condition === undefined) return undefined\n\n const objectTypeId =\n grant.capability === \"view\" && grant.target === \"object\" ? onlyId(grant.selection) : undefined\n\n if (objectTypeId === undefined) {\n throw new SecurityValidationError(\n `[Sixb] Role '${roleId}' declares a condition on a grant that is not a view grant on one object type. Write can.view(Type).where(...).`\n )\n }\n\n const subject = viewConditionSubject({ roleId, objectTypeId })\n\n if (!ontology) {\n throw new SecurityValidationError(`[Sixb] ${subject} needs the ontology to be validated.`)\n }\n\n const objectTypeIds = [objectTypeId, ...ontology.listSubTypes(objectTypeId)]\n\n try {\n const validated = validateObjectQueryWithAdmission(\n {\n kind: \"filter\",\n input: { kind: \"start\", objectTypeId, includeSubtypes: true },\n predicate: grant.condition,\n },\n { ontology },\n unmarkedPropertiesOnly(subject, objectTypeIds, ontology)\n )\n\n if (validated.query.kind !== \"filter\") {\n throw new Error(`[Sixb] ${subject} did not validate as a filter.`)\n }\n\n const ordered = orderedTextComparison(validated.query.predicate)\n if (ordered) {\n throw new SecurityValidationError(\n `[Sixb] ${subject} compares '${objectTypeId}.${ordered.propertyId}' with ${ordered.op}(). Storage providers order text differently, so a condition cannot order text: compare with eq, neq, in or contains instead.`\n )\n }\n\n return {\n roleId,\n objectTypeId,\n predicate: deepFreeze(structuredClone(validated.query.predicate)),\n }\n } catch (error) {\n if (!(error instanceof ObjectQueryValidationError)) throw error\n\n const reasons = error.issues.map((issue) => issue.message).join(\"; \")\n throw new SecurityValidationError(`[Sixb] ${subject}: ${reasons}`)\n }\n}\n\n/**\n * Compile each condition once against the object storage, at startup. A condition the storage\n * cannot read would otherwise fail every read of its type, for every reader it applies to.\n *\n * Each reader binds `currentUser()` to its own user; the check binds it to a placeholder, so the\n * storage compiles the comparison a user's reads run.\n */\nexport function assertViewConditionsReadable(input: {\n readonly projectId: string\n readonly conditions: readonly ViewCondition[]\n readonly objectStorage: Pick<ObjectReadScopeFactory, \"createConditionalReadScope\">\n readonly getSubTypes: (objectTypeId: string) => readonly string[]\n}): void {\n for (const condition of input.conditions) {\n const predicate = bindCurrentUserPredicate(condition.predicate, STARTUP_CHECK_USER)\n const objectTypeIds = [condition.objectTypeId, ...input.getSubTypes(condition.objectTypeId)]\n\n try {\n input.objectStorage.createConditionalReadScope({\n projectId: input.projectId,\n scope: compileConditionalObjectReadScope({\n kind: \"conditional\",\n conditions: objectTypeIds.map((objectTypeId) => ({ objectTypeId, predicate })),\n }),\n })\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n throw new SecurityValidationError(\n `[Sixb] ${viewConditionSubject(condition)} cannot be read by the configured object storage: ${reason}`,\n { cause: error }\n )\n }\n }\n}\n\nconst STARTUP_CHECK_USER = Object.freeze({ type: \"user\", id: \"usr_sixb_startup_check\" } as const)\n\nfunction viewConditionSubject(condition: Pick<ViewCondition, \"roleId\" | \"objectTypeId\">): string {\n return `Role '${condition.roleId}': can.view(${condition.objectTypeId}).where(...)`\n}\n\n/**\n * PostgreSQL orders text by the database collation, SQLite and the in-memory store by code unit, so\n * `code.gte(\"M\")` would show different objects depending on the store.\n */\nfunction orderedTextComparison(\n predicate: ObjectQueryPredicate\n): { readonly propertyId: string; readonly op: string } | null {\n switch (predicate.op) {\n case \"and\":\n case \"or\":\n for (const item of predicate.items) {\n const ordered = orderedTextComparison(item)\n if (ordered) return ordered\n }\n return null\n\n case \"not\":\n return orderedTextComparison(predicate.item)\n\n case \"lt\":\n case \"lte\":\n case \"gt\":\n case \"gte\":\n return predicate.scalarKind === \"string\" || predicate.scalarKind === \"uuid\"\n ? { propertyId: predicate.propertyId, op: predicate.op }\n : null\n\n default:\n return null\n }\n}\n\nfunction onlyId(selection: Selection): string | undefined {\n if (selection.all || selection.ids.length !== 1) return undefined\n return selection.ids[0]\n}\n\n/**\n * Refuse a condition that reads a marked property, on the type or on any subtype the grant covers.\n * Which objects match would reveal values their reader cannot read.\n *\n * The validator walks the condition and reports each property it reads; its own issues are raised\n * before this denial.\n */\nfunction unmarkedPropertiesOnly(\n subject: string,\n objectTypeIds: readonly string[],\n ontology: OntologyRegistry\n): ObjectQuerySemanticAdmission {\n const state = Object.freeze({})\n\n const admission: ObjectQuerySemanticAdmission = {\n empty: () => state,\n source: () => ({ state }),\n edge: () => ({ state }),\n set: () => state,\n property: ({ propertyId }) => {\n for (const objectTypeId of objectTypeIds) {\n const property = ontology\n .getObjectTypeById(objectTypeId)\n ?.properties.find((candidate) => candidate.id === propertyId)\n\n const markings = property?.markings ?? []\n if (markings.length === 0) continue\n\n return new SecurityValidationError(\n `[Sixb] ${subject} reads '${objectTypeId}.${propertyId}', which carries [${markings.join(\", \")}]. A condition can only read unmarked properties.`\n )\n }\n\n return undefined\n },\n }\n\n return Object.freeze(admission)\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (typeof value !== \"object\" || value === null) return value\n\n for (const child of Object.values(value)) deepFreeze(child)\n return Object.freeze(value)\n}\n",
|
|
22
|
+
"import { type ResolvedRole, resolveRoleGrants, resolveRoleViewConditions } from \"../authorization\"\nimport type { OntologyRegistry } from \"../ontology\"\nimport type {\n GroupDefinition,\n MarkingDefinition,\n MembershipPolicyDefinition,\n RoleDefinition,\n} from \"./types\"\nimport { validateSecurityDefinitionsAtStartup } from \"./validation\"\nimport { resolveViewCondition, type ViewCondition } from \"./view-conditions\"\n\n/** Read-only access to validated security definitions and resolved role grants. */\nexport interface SecurityDefinitionCatalog {\n listMarkings(): readonly MarkingDefinition[]\n getMarkingById(markingId: string): MarkingDefinition | null\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 markings?: readonly MarkingDefinition[]\n readonly groups?: readonly GroupDefinition[]\n readonly roles?: readonly RoleDefinition[]\n readonly membershipPolicies?: readonly MembershipPolicyDefinition[]\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 shareIds?: ReadonlySet<string>\n readonly getSubTypes?: (objectTypeId: string) => readonly string[]\n readonly ontology?: OntologyRegistry\n}\n\nexport class SecurityRegistry implements SecurityDefinitionCatalog {\n private readonly markingsById: ReadonlyMap<string, MarkingDefinition>\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 private readonly viewConditions: readonly ViewCondition[]\n\n constructor(input: SecurityRegistryOptions) {\n const definitions = validateSecurityDefinitionsAtStartup({\n markings: input.markings ?? [],\n groups: input.groups ?? [],\n roles: input.roles ?? [],\n membershipPolicies: input.membershipPolicies ?? [],\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 shareIds: input.shareIds,\n })\n\n // Conditions are checked here rather than with the other grant rules: those also load in the\n // browser through `defineGroup`, and a condition needs the object-query validator.\n this.viewConditions = definitions.roles.flatMap((role) =>\n role.grants.flatMap((grant) => resolveViewCondition(role.id, grant, input.ontology) ?? [])\n )\n\n const universe = {\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 shareIds: input.shareIds ?? new Set<string>(),\n getSubTypes: input.getSubTypes ?? (() => []),\n }\n\n this.markingsById = definitions.markingsById\n this.groupsById = definitions.groupsById\n this.rolesById = definitions.rolesById\n this.membershipPoliciesById = definitions.membershipPoliciesById\n this.resolvedRoles = definitions.roles.map((role) => {\n const grants = resolveRoleGrants(role, universe)\n const viewConditions = resolveRoleViewConditions(\n this.viewConditions.filter((condition) => condition.roleId === role.id),\n grants,\n universe\n )\n\n return {\n id: role.id,\n grantedToGroupIds: role.grantedToGroupIds,\n grants,\n ...(viewConditions.size > 0 ? { viewConditions } : {}),\n clearances: new Set(role.clearances ?? []),\n }\n })\n }\n\n listMarkings(): readonly MarkingDefinition[] {\n return [...this.markingsById.values()]\n }\n\n getMarkingById(markingId: string): MarkingDefinition | null {\n return this.markingsById.get(markingId) ?? null\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 /** Every role's `can.view(Type).where(...)`, validated, in declaration order. */\n listViewConditions(): readonly ViewCondition[] {\n return this.viewConditions\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",
|
|
23
|
+
"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 | \"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",
|
|
24
|
+
"import { 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): 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 (!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.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 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 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 bearer: input.bearer\n ? {\n clientName: assertNonEmpty(input.bearer.clientName, \"Session client name\"),\n accessExpiresAt: cloneDate(input.bearer.accessExpiresAt),\n refreshTokenHash: assertNonEmpty(input.bearer.refreshTokenHash, \"Refresh token hash\"),\n }\n : undefined,\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.subject.id, \"Access token subject id\")\n const tokenHash = assertNonEmpty(input.tokenHash, \"Access token hash\")\n\n assertAccessTokenSubject(input.kind, input.subject.type)\n assertAccessTokenSubjectExists(state, projectId, input.subject.type, 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 subject: { type: input.subject.type, id: 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[\"subject\"][\"type\"]\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[\"subject\"][\"type\"],\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",
|
|
25
|
+
"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(\n (token) =>\n input.subject === undefined ||\n (token.subject.type === input.subject.type && token.subject.id === input.subject.id)\n )\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",
|
|
26
|
+
"import type { AccessTokenKind, Principal } from \"../../auth\"\nimport type { AuthorizablePrincipal } from \"../../execution/types\"\n\nexport type UserStatus = \"active\" | \"suspended\"\nexport type ServiceAccountStatus = \"active\" | \"suspended\"\nexport type InvitationStatus = \"pending\" | \"accepted\" | \"revoked\"\n/** `directory`: owned by the identity provider, and synced to its groups on every sign-in. */\nexport type GroupMembershipSource = \"invitation\" | \"manual\" | \"agent\" | \"directory\"\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 /** Service accounts never sign in, so no identity provider owns their memberships. */\n readonly source: Exclude<GroupMembershipSource, \"directory\">\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 /** The web app a browser session belongs to. A bearer session belongs to none and ignores it. */\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 /** Present when a native client holds the session as bearer tokens instead of a cookie. */\n readonly bearer?: BearerSessionState\n}\n\n/**\n * A native client's credentials for its session. `tokenHash` on the session is the current access\n * token's hash; the refresh token rotates on every refresh.\n */\nexport interface BearerSessionState {\n /** Self-reported client label, such as \"sixb CLI on alex-mbp\". Display only. */\n readonly clientName: string\n readonly accessExpiresAt: Date\n readonly refreshTokenHash: string\n /** The refresh token the last rotation replaced, accepted briefly in case its response was lost. */\n readonly previousRefreshTokenHash?: string\n readonly refreshedAt?: Date\n}\n\nexport type RotateSessionRefreshTokenResult =\n | { readonly status: \"rotated\"; readonly session: SessionRecord }\n /** A replaced refresh token came back after the grace window; the session is now revoked. */\n | { readonly status: \"reused\" }\n | { readonly status: \"invalid\" }\n\nexport interface AccessTokenRecord {\n readonly id: string\n readonly projectId: string\n readonly name: string\n readonly kind: AccessTokenKind\n readonly subject: AuthorizablePrincipal\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 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 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 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\n/** Omitted fields stay unchanged, and `null` clears one. */\nexport interface UpdateAuthUserProfileInput {\n readonly projectId: string\n readonly id: string\n readonly displayName?: string | null\n readonly avatarUrl?: string | null\n readonly updatedAt?: Date\n}\n\n/** A change to one user, with the user as the change found them, read in the same atomic step. */\nexport interface UpdateAuthUserResult {\n readonly user: UserRecord\n readonly previousUser: UserRecord\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 /**\n * Keep users whose display name or email contains this text, ignoring case. Matched literally:\n * `%` and `_` are plain characters. `total` and `hasMore` count only the matches. SQLite ignores\n * case for ASCII letters only.\n */\n readonly search?: string\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: ServiceAccountGroupMembershipRecord[\"source\"]\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 tokenHash: string\n readonly createdAt: Date\n readonly expiresAt: Date\n readonly absoluteExpiresAt?: Date\n readonly userAgent?: string\n readonly ipAddress?: string\n readonly bearer?: Pick<BearerSessionState, \"clientName\" | \"accessExpiresAt\" | \"refreshTokenHash\">\n}\n\nexport interface CreateAuthAccessTokenInput {\n readonly id: string\n readonly projectId: string\n readonly name: string\n readonly kind: AccessTokenKind\n readonly subject: AuthorizablePrincipal\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 subject?: AuthorizablePrincipal\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 ListAuthSessionsInput {\n readonly projectId: string\n readonly userId: string\n readonly limit: number\n /**\n * Continue a list: sessions created at or before `createdAt`, past the first `skip` of those\n * created exactly then, which the previous pages returned.\n */\n readonly before?: { readonly createdAt: Date; readonly skip: number }\n}\n\nexport interface ListAuthSessionsResult {\n readonly sessions: readonly SessionRecord[]\n readonly hasMore: boolean\n}\n\nexport interface CompleteAuthSessionInput {\n readonly id: string\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 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 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 createdAt: Date\n readonly expiresAt: Date\n}\n\nexport interface CompleteDeviceAuthorizationInput {\n readonly projectId: string\n readonly id: string\n readonly deviceCodeHash: string\n /**\n * The session to start for the approving user: a bearer session for a native client, or a\n * cookie session for a browser that asked to be approved from another one.\n */\n readonly session: CreateAuthSessionInput\n readonly completedAt: Date\n}\n\nexport interface CompleteDeviceAuthorizationResult {\n readonly authorization: DeviceAuthorizationRecord\n readonly session: SessionRecord\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 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 /**\n * An address the strategy has already decided to trust. Without an identity for `subject`, it\n * links the user who has this email, or claims this email's invitation for a new user.\n */\n readonly email: string\n /**\n * The name and picture the provider sends. Every sign-in sets them on the user, and one left out\n * keeps the stored value. `updatedAt` moves only when one of them changes.\n */\n readonly displayName?: string\n readonly avatarUrl?: string\n readonly claims?: Readonly<Record<string, unknown>>\n readonly allowUserCreationWithoutInvitation?: boolean\n readonly manualGroupIds?: readonly string[]\n /**\n * The groups the identity provider grants this user. When present, the user's `directory`\n * memberships become exactly these; memberships from any other source are never touched, and a\n * group the user already has from another source keeps it. Omitted, nothing is synced.\n */\n readonly directoryGroupIds?: 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 * The user as this sign-in found them, before it changed their profile, or `null` when this\n * sign-in created them.\n */\n readonly previousUser: UserRecord | null\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 /** The users of the project with these ids, in any order. Ids no user has are skipped. */\n getByIds(params: {\n readonly projectId: string\n readonly ids: readonly string[]\n }): Promise<readonly UserRecord[]>\n getByEmail(params: {\n readonly projectId: string\n readonly email: string\n }): Promise<UserRecord | null>\n /**\n * Update only the provided fields; omitted fields must remain unchanged atomically. When no\n * value changes, nothing is written, so `updatedAt` stays as it was.\n */\n updateProfile(input: UpdateAuthUserProfileInput): Promise<UpdateAuthUserResult>\n updateStatus(input: UpdateAuthUserStatusInput): Promise<UpdateAuthUserResult>\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 // All active sessions for a user, 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 /** Every session of a user, revoked and expired ones too, newest first: a sign-in history. */\n listByUserId(params: ListAuthSessionsInput): Promise<ListAuthSessionsResult>\n /** A live browser (cookie) session whose secret hashes to `tokenHash`. */\n findValidByTokenHash(params: {\n readonly projectId: string\n readonly id: string\n readonly tokenHash: string\n readonly now: Date\n }): Promise<SessionRecord | null>\n /** A live bearer session whose current, unexpired access token hashes to `tokenHash`. */\n findValidByAccessTokenHash(params: {\n readonly projectId: string\n readonly id: string\n readonly tokenHash: string\n readonly now: Date\n }): Promise<SessionRecord | null>\n /**\n * Atomically replace a live bearer session's tokens. The current refresh token rotates; the one\n * it replaced also rotates within `reuseGraceMs` of that replacement. Presenting it later revokes\n * the session. `next.expiresAt` extends the idle deadline, never past the absolute one.\n */\n rotateRefreshToken(params: {\n readonly projectId: string\n readonly id: string\n readonly refreshTokenHash: string\n readonly now: Date\n readonly reuseGraceMs: number\n readonly next: {\n readonly tokenHash: string\n readonly accessExpiresAt: Date\n readonly refreshTokenHash: string\n readonly expiresAt: Date\n }\n }): Promise<RotateSessionRefreshTokenResult>\n renewIfValid(params: {\n readonly projectId: string\n readonly id: string\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 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(\n input: SuspendUserAndRevokeSessionsInput\n ): Promise<UpdateAuthUserResult>\n}\n",
|
|
27
|
+
"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 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",
|
|
28
|
+
"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",
|
|
29
|
+
"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",
|
|
30
|
+
"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",
|
|
31
|
+
"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",
|
|
32
|
+
"import { 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 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 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",
|
|
33
|
+
"import { 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 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 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",
|
|
34
|
+
"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",
|
|
35
|
+
"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",
|
|
36
|
+
"import { AuthStorageError } from \"../errors\"\nimport type {\n AuthSessionStore,\n CreateAuthSessionInput,\n ListAuthSessionsInput,\n ListAuthSessionsResult,\n RotateSessionRefreshTokenResult,\n SessionRecord,\n} from \"../types\"\nimport type { AuthStorageState } from \"./shared\"\nimport {\n cloneDate,\n cloneOptionalRecord,\n cloneRecord,\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 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 listByUserId(params: ListAuthSessionsInput): Promise<ListAuthSessionsResult> {\n const before = params.before\n const offset = before?.skip ?? 0\n const sessions = [...this.state.sessions.values()]\n .filter((session) => session.projectId === params.projectId)\n .filter((session) => session.userId === params.userId)\n .filter((session) => !before || session.createdAt <= before.createdAt)\n .sort((a, b) => {\n const created = b.createdAt.getTime() - a.createdAt.getTime()\n if (created !== 0) return created\n return a.id < b.id ? 1 : a.id > b.id ? -1 : 0\n })\n\n return {\n sessions: sessions.slice(offset, offset + params.limit).map(cloneRecord),\n hasMore: sessions.length > offset + params.limit,\n }\n }\n\n async findValidByTokenHash(params: {\n readonly projectId: string\n readonly id: string\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.bearer ||\n session.tokenHash !== params.tokenHash ||\n !isActiveSession(session, params.now)\n ) {\n return null\n }\n\n return cloneRecord(session)\n }\n\n async findValidByAccessTokenHash(params: {\n readonly projectId: string\n readonly id: string\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?.bearer ||\n session.tokenHash !== params.tokenHash ||\n session.bearer.accessExpiresAt <= params.now ||\n !isActiveSession(session, params.now)\n ) {\n return null\n }\n\n return cloneRecord(session)\n }\n\n async rotateRefreshToken(\n params: Parameters<AuthSessionStore[\"rotateRefreshToken\"]>[0]\n ): Promise<RotateSessionRefreshTokenResult> {\n const key = sessionKey(params.projectId, params.id)\n const session = this.state.sessions.get(key)\n if (!session?.bearer || !isActiveSession(session, params.now)) {\n return { status: \"invalid\" }\n }\n\n const { bearer } = session\n const replacedRecently =\n bearer.previousRefreshTokenHash === params.refreshTokenHash &&\n bearer.refreshedAt !== undefined &&\n params.now.getTime() - bearer.refreshedAt.getTime() <= params.reuseGraceMs\n if (bearer.refreshTokenHash !== params.refreshTokenHash && !replacedRecently) {\n if (bearer.previousRefreshTokenHash !== params.refreshTokenHash) {\n return { status: \"invalid\" }\n }\n this.state.sessions.set(key, cloneRecord({ ...session, revokedAt: cloneDate(params.now) }))\n return { status: \"reused\" }\n }\n\n const requestedExpiresAt = session.absoluteExpiresAt\n ? new Date(Math.min(params.next.expiresAt.getTime(), session.absoluteExpiresAt.getTime()))\n : params.next.expiresAt\n const next: SessionRecord = {\n ...session,\n tokenHash: params.next.tokenHash,\n expiresAt: new Date(Math.max(session.expiresAt.getTime(), requestedExpiresAt.getTime())),\n lastSeenAt: cloneDate(params.now),\n bearer: {\n clientName: bearer.clientName,\n accessExpiresAt: cloneDate(params.next.accessExpiresAt),\n refreshTokenHash: params.next.refreshTokenHash,\n previousRefreshTokenHash: bearer.refreshTokenHash,\n refreshedAt: cloneDate(params.now),\n },\n }\n this.state.sessions.set(key, cloneRecord(next))\n return { status: \"rotated\", session: cloneRecord(next) }\n }\n\n async renewIfValid(params: {\n readonly projectId: string\n readonly id: string\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.bearer ||\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 revokedAt: Date\n }): Promise<readonly SessionRecord[]> {\n return revokeActiveSessionsForUser(\n this.state,\n params.projectId,\n params.userId,\n params.revokedAt\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",
|
|
37
|
+
"import { paginate } from \"../../pagination\"\nimport { AuthStorageError } from \"../errors\"\nimport type {\n AuthUserStore,\n CreateAuthUserInput,\n ListAuthUsersInput,\n ListAuthUsersResult,\n UpdateAuthUserProfileInput,\n UpdateAuthUserResult,\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 getByIds(params: {\n readonly projectId: string\n readonly ids: readonly string[]\n }): Promise<readonly UserRecord[]> {\n return [...new Set(params.ids)].flatMap((id) => {\n const record = this.state.users.get(userKey(params.projectId, id))\n return record ? [cloneRecord(record)] : []\n })\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<UpdateAuthUserResult> {\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 displayName = profileValue(input.displayName, existing.displayName)\n const avatarUrl = profileValue(input.avatarUrl, existing.avatarUrl)\n if (displayName === existing.displayName && avatarUrl === existing.avatarUrl) {\n return { user: cloneRecord(existing), previousUser: cloneRecord(existing) }\n }\n\n const next: UserRecord = {\n ...existing,\n displayName,\n avatarUrl,\n updatedAt: dateOrNow(input.updatedAt),\n }\n this.state.users.set(key, cloneRecord(next))\n return { user: cloneRecord(next), previousUser: cloneRecord(existing) }\n }\n\n async updateStatus(input: UpdateAuthUserStatusInput): Promise<UpdateAuthUserResult> {\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 { user: cloneRecord(next), previousUser: cloneRecord(existing) }\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 search = input.search?.toLowerCase()\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 .filter((user) => (search === undefined ? true : userMatches(user, search)))\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\n// Omitted keeps the current value, and `null` clears it.\nfunction profileValue(\n value: string | null | undefined,\n current: string | undefined\n): string | undefined {\n return value === undefined ? current : (value ?? undefined)\n}\n\nfunction userMatches(user: UserRecord, search: string): boolean {\n return (\n (user.displayName?.toLowerCase().includes(search) ?? false) ||\n user.email.toLowerCase().includes(search)\n )\n}\n",
|
|
38
|
+
"import { AuthStorageError } from \"../errors\"\nimport type {\n AuthStorage,\n CompleteDeviceAuthorizationInput,\n CompleteDeviceAuthorizationResult,\n CompleteMagicLinkSignInInput,\n CompleteOidcSignInInput,\n CompleteSignInResult,\n GroupMembershipRecord,\n GroupMembershipSource,\n InvitationRecord,\n SessionRecord,\n SuspendUserAndRevokeSessionsInput,\n UpdateAuthUserResult,\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 createAuthStorageState,\n createSessionRecord,\n deviceAuthorizationKey,\n getActiveInvitationByEmail,\n getUserByEmail,\n identityKey,\n invitationKey,\n magicLinkKey,\n normalizeClaims,\n normalizeEmail,\n normalizeGroupIds,\n oidcAttemptKey,\n removeGroupMembershipRecord,\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.session.projectId !== input.projectId ||\n input.session.userId !== authorization.approvedUserId\n ) {\n throw new AuthStorageError(\n \"invalid_device_authorization\",\n \"[Sixb] Device session is invalid.\"\n )\n }\n const session = createSessionRecord(this.state, input.session)\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), session: cloneRecord(session) }\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 validateCompleteSessionInput(this.state, projectId, input.session)\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 const previousUser = existingUser ? cloneRecord(existingUser) : null\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.applyGroups({\n completedAt,\n source: \"manual\",\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 previousUser,\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 (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 && !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 validateCompleteSessionInput(this.state, projectId, input.session)\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 const previousUser = user ? cloneRecord(user) : null\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 } else {\n user = this.refreshProviderProfile(user, input, completedAt)\n }\n\n const invitation = this.acceptInvitationAndApplyGroups({\n activeInvitation,\n completedAt,\n projectId,\n user,\n })\n const memberships = this.syncDirectoryGroups({\n completedAt,\n groupIds: input.directoryGroupIds,\n projectId,\n userId: user.id,\n existing: this.applyGroups({\n completedAt,\n source: \"manual\",\n groupIds: manualGroupIds,\n projectId,\n userId: user.id,\n existing: invitation.memberships,\n }),\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 previousUser,\n }\n }\n\n async suspendUserAndRevokeSessions(\n input: SuspendUserAndRevokeSessionsInput\n ): Promise<UpdateAuthUserResult> {\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 { user: cloneRecord(next), previousUser: cloneRecord(existing) }\n }\n\n // The identity provider owns the name and picture it sends: every sign-in overwrites them, and\n // one it leaves out keeps the stored value.\n private refreshProviderProfile(\n user: UserRecord,\n input: CompleteOidcSignInInput,\n updatedAt: Date\n ): UserRecord {\n const displayName = input.displayName ?? user.displayName\n const avatarUrl = input.avatarUrl ?? user.avatarUrl\n if (displayName === user.displayName && avatarUrl === user.avatarUrl) {\n return user\n }\n\n const next: UserRecord = { ...user, displayName, avatarUrl, updatedAt: cloneDate(updatedAt) }\n this.state.users.set(userKey(user.projectId, user.id), cloneRecord(next))\n return 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 applyGroups(input: {\n readonly completedAt: Date\n readonly groupIds: readonly string[]\n readonly projectId: string\n readonly source: GroupMembershipSource\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: input.source,\n createdAt: input.completedAt,\n })\n )\n }\n return memberships\n }\n // Directory memberships become exactly `groupIds`. A group the user already holds from another\n // source keeps that source, and memberships from other sources are never removed.\n private syncDirectoryGroups(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 if (!input.groupIds) {\n return input.existing\n }\n\n const groupIds = normalizeGroupIds(input.groupIds)\n const stale = [...this.state.groupMemberships.values()].filter(\n (membership) =>\n membership.projectId === input.projectId &&\n membership.userId === input.userId &&\n membership.source === \"directory\" &&\n !groupIds.includes(membership.groupId)\n )\n for (const membership of stale) {\n removeGroupMembershipRecord(this.state, membership)\n }\n\n return this.applyGroups({ ...input, groupIds, source: \"directory\" })\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 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",
|
|
39
|
+
"import { assertAuthorized } from \"../authorization\"\nimport { isUserRef, type UserRef } from \"../ontology/user-ref\"\nimport type { SixbRuntimeContext } from \"../runtime/types\"\nimport type { UserRecord, UserStatus } from \"../storage\"\n\nconst DEFAULT_LIMIT = 50\nconst MAX_LIMIT = 200\nconst MAX_SEARCH_LENGTH = 200\n\n/** A member as the directory shows them. Read from auth storage, never from what a writer stored. */\nexport interface UserProfile {\n readonly id: string\n readonly email: string\n readonly displayName?: string\n readonly avatarUrl?: string\n readonly status: UserStatus\n}\n\nexport interface ListUsersInput {\n /** Which members to list. Defaults to `\"active\"`. */\n readonly status?: UserStatus | \"all\"\n /**\n * Keep members whose display name or email contains this text, ignoring case. At most 200\n * characters.\n */\n readonly search?: string\n /** From 1 to 200. Defaults to 50. */\n readonly limit?: number\n readonly offset?: number\n}\n\n/** One page of members, oldest first. */\nexport interface UsersPage {\n readonly users: readonly UserProfile[]\n readonly hasMore: boolean\n /** Every member matching the filters, across all pages. */\n readonly total: number\n}\n\n/** The project's member directory. Reading it requires `can.view(project.users)`. */\nexport interface UsersRuntime {\n /** The member's profile, suspended or not, or `null` when no member has this id. */\n get(user: UserRef): Promise<UserProfile | null>\n list(input?: ListUsersInput): Promise<UsersPage>\n}\n\nexport function createUsersRuntime(runtime: SixbRuntimeContext): UsersRuntime {\n const assertReadable = () => assertAuthorized(runtime, { kind: \"users.view\" })\n\n return {\n get: async (user) => {\n assertReadable()\n\n if (!isUserRef(user)) {\n throw new Error(\"[Sixb] users.get expects a user reference, such as userRef(id).\")\n }\n\n const users = runtime.storage.auth?.users\n if (!users) return null\n\n const record = await users.getById({ projectId: runtime.projectId, id: user.id })\n return record ? toUserProfile(record) : null\n },\n\n list: async (input = {}) => {\n assertReadable()\n\n const limit = listLimit(input.limit)\n const offset = listOffset(input.offset)\n const search = listSearch(input.search)\n\n const users = runtime.storage.auth?.users\n if (!users) return { users: [], hasMore: false, total: 0 }\n\n const page = await users.list({\n projectId: runtime.projectId,\n ...statusFilter(input.status),\n ...(search === undefined ? {} : { search }),\n limit,\n offset,\n order: \"asc\",\n })\n\n return {\n users: page.users.map(toUserProfile),\n hasMore: page.hasMore,\n total: page.total,\n }\n },\n }\n}\n\n/** Only the fields the directory shows: no project id, no timestamps. */\nexport function toUserProfile(record: UserRecord): UserProfile {\n return {\n id: record.id,\n email: record.email,\n ...(record.displayName === undefined ? {} : { displayName: record.displayName }),\n ...(record.avatarUrl === undefined ? {} : { avatarUrl: record.avatarUrl }),\n status: record.status,\n }\n}\n\nfunction statusFilter(status: ListUsersInput[\"status\"] = \"active\") {\n if (status === \"all\") return {}\n if (status === \"active\" || status === \"suspended\") return { statuses: [status] }\n\n throw new Error(`[Sixb] users.list status must be \"active\", \"suspended\", or \"all\".`)\n}\n\nfunction listSearch(search: string | undefined): string | undefined {\n const trimmed = search?.trim()\n if (!trimmed) return undefined\n if (trimmed.length <= MAX_SEARCH_LENGTH) return trimmed\n\n throw new Error(`[Sixb] users.list search must be at most ${MAX_SEARCH_LENGTH} characters.`)\n}\n\nfunction listLimit(limit: number | undefined): number {\n if (limit === undefined) return DEFAULT_LIMIT\n if (Number.isInteger(limit) && limit >= 1 && limit <= MAX_LIMIT) return limit\n\n throw new Error(`[Sixb] users.list limit must be an integer from 1 to ${MAX_LIMIT}.`)\n}\n\nfunction listOffset(offset: number | undefined): number {\n if (offset === undefined) return 0\n if (Number.isInteger(offset) && offset >= 0) return offset\n\n throw new Error(\"[Sixb] users.list offset must be a non-negative integer.\")\n}\n",
|
|
40
|
+
"import type { EventDraft, PropertyChange, UserProfileUpdatedEvent } from \"../events/types\"\nimport type { CompleteSignInResult, InvitationRecord, UserRecord } from \"../storage/auth\"\nimport { toUserProfile } from \"../users/execution\"\nimport type { AuthenticatedUserRequestSession } from \"./types\"\n\ntype ProfileChanges = UserProfileUpdatedEvent[\"payload\"][\"changes\"]\n\n/**\n * What a completed sign-in tells the project: a new member, or the profile their identity provider\n * changed. A sign-in that changed nothing tells nothing.\n */\nexport function signInEvents(result: CompleteSignInResult): readonly EventDraft[] {\n const user = toUserProfile(result.user)\n\n if (result.previousUser === null) {\n return [\n {\n type: \"user.joined\",\n payload: {\n user,\n ...(result.invitation ? { invitationId: result.invitation.id } : {}),\n },\n idempotencyKey: `user.joined:${user.id}`,\n },\n ]\n }\n\n const changes = profileChanges(result.previousUser, result.user)\n if (!hasChanges(changes)) return []\n\n return [{ type: \"user.profile.updated\", payload: { user, changes } }]\n}\n\n/** A member edited their own profile. Saving the values it already had tells nothing. */\nexport function profileUpdatedEvents(\n caller: AuthenticatedUserRequestSession,\n previousUser: UserRecord,\n user: UserRecord\n): readonly EventDraft[] {\n const changes = profileChanges(previousUser, user)\n if (!hasChanges(changes)) return []\n\n return [\n {\n type: \"user.profile.updated\",\n payload: { user: toUserProfile(user), changes, requestedBy: requester(caller) },\n },\n ]\n}\n\nexport function statusChangedEvents(\n caller: AuthenticatedUserRequestSession,\n previousUser: UserRecord,\n user: UserRecord\n): readonly EventDraft[] {\n if (previousUser.status === user.status) return []\n\n return [\n {\n type: user.status === \"suspended\" ? \"user.suspended\" : \"user.reactivated\",\n payload: { user: toUserProfile(user), requestedBy: requester(caller) },\n },\n ]\n}\n\nexport function invitedEvents(\n caller: AuthenticatedUserRequestSession,\n invitation: InvitationRecord\n): readonly EventDraft[] {\n return [\n {\n type: \"user.invited\",\n payload: {\n invitationId: invitation.id,\n email: invitation.email,\n expiresAt: invitation.expiresAt.toISOString(),\n requestedBy: requester(caller),\n },\n },\n ]\n}\n\nfunction profileChanges(before: UserRecord, after: UserRecord): ProfileChanges {\n const displayName = fieldChange(before.displayName, after.displayName)\n const avatarUrl = fieldChange(before.avatarUrl, after.avatarUrl)\n\n return {\n ...(displayName ? { displayName } : {}),\n ...(avatarUrl ? { avatarUrl } : {}),\n }\n}\n\nfunction fieldChange(\n before: string | undefined,\n after: string | undefined\n): PropertyChange<string> | undefined {\n if (after === undefined) {\n return before === undefined ? undefined : { operation: \"cleared\", before, after: null }\n }\n\n if (before === undefined) return { operation: \"created\", after }\n if (before === after) return undefined\n\n return { operation: \"updated\", before, after }\n}\n\nfunction hasChanges(changes: ProfileChanges): boolean {\n return changes.displayName !== undefined || changes.avatarUrl !== undefined\n}\n\n// Only the principal: the session behind it is not part of the event.\nfunction requester(caller: AuthenticatedUserRequestSession) {\n return { type: caller.principal.type, id: caller.principal.id }\n}\n",
|
|
41
|
+
"import type { AuthenticatedAuthSession } from \"./types\"\n\ninterface SessionCacheEntry {\n readonly tokenHash: string\n readonly transport: \"cookie\" | \"bearer\"\n readonly session: AuthenticatedAuthSession\n readonly expiresAtMs: number\n}\n\nexport interface SessionCacheGetInput {\n readonly sessionId: string\n readonly tokenHash: string\n /** A cookie is only ever answered from a cookie entry, and a bearer token from a bearer entry. */\n readonly transport: \"cookie\" | \"bearer\"\n readonly nowMs: number\n}\n\nexport interface SessionCacheSetInput {\n readonly sessionId: string\n readonly tokenHash: string\n readonly nowMs: number\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 and transport 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.transport !== input.transport\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, or a bearer session its access token.\n const bearer = input.session.session.bearer\n const expiresAtMs = Math.min(\n input.nowMs + this.ttlMs,\n input.sessionExpiresAtMs,\n input.sessionAbsoluteExpiresAtMs ?? Number.POSITIVE_INFINITY,\n bearer?.accessExpiresAt.getTime() ?? 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 transport: bearer ? \"bearer\" : \"cookie\",\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",
|
|
42
|
+
"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\nexport const SESSION_ACCESS_TOKEN_PREFIX = \"sixb_at_\"\nexport const SESSION_REFRESH_TOKEN_PREFIX = \"sixb_rt_\"\n\nexport interface BearerSessionTokens {\n readonly accessToken: string\n readonly refreshToken: string\n readonly tokenHash: string\n readonly refreshTokenHash: string\n}\n\n/** Fresh access and refresh tokens for a native client's session. Only their hashes are stored. */\nexport function createBearerSessionTokens(sessionId: string): BearerSessionTokens {\n const accessSecret = generateSessionSecret()\n const refreshSecret = generateSessionSecret()\n return {\n accessToken: `${SESSION_ACCESS_TOKEN_PREFIX}${formatSessionCookieValue(sessionId, accessSecret)}`,\n refreshToken: `${SESSION_REFRESH_TOKEN_PREFIX}${formatSessionCookieValue(sessionId, refreshSecret)}`,\n tokenHash: hashSessionSecret(accessSecret),\n refreshTokenHash: hashSessionSecret(refreshSecret),\n }\n}\n\n/** The session id and secret in a bearer session token, or null when it is not one. */\nexport function parseBearerSessionToken(\n prefix: typeof SESSION_ACCESS_TOKEN_PREFIX | typeof SESSION_REFRESH_TOKEN_PREFIX,\n value: string\n): SessionCookieParts | null {\n return value.startsWith(prefix) ? parseSessionCookieValue(value.slice(prefix.length)) : null\n}\n",
|
|
43
|
+
"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 UserIdentityRecord,\n UserRecord,\n} from \"../storage/auth\"\nimport type { UserProfile } from \"../users\"\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/** A signed-in person: the only principal who talks to the Agent or takes part in a thread. */\nexport type UserPrincipal = Extract<Principal, { readonly type: \"user\" }>\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 type AuthStrategyKind = \"magicLink\" | \"oidc\" | \"dev\" | \"disabled\"\n\n/** A profile field an identity provider can own. */\nexport type ProfileField = \"displayName\" | \"avatarUrl\"\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 * The profile fields this strategy's provider sets at every sign-in of the person behind\n * `identity`, so people cannot edit them in Sixb. Omitted, the strategy manages none.\n */\n providerProfileFields?(identity: UserIdentityRecord): readonly ProfileField[]\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 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 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 /** The name the person gave. Used only when this sign-in creates their account. */\n readonly displayName?: string\n readonly now?: Date\n}\n\nexport interface MagicLinkCallbackResult extends CompleteSignInResult {\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 /** The link will create an account, so the confirmation page may ask for a name. */\n readonly firstSignIn?: true\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 returnTo: string\n readonly requestOrigin: string\n readonly now?: Date\n}\n\nexport interface OidcStartSignInResult {\n readonly redirectTo: string\n /**\n * The `state` sent to the provider. The server keeps it in a cookie until `expiresAt` and\n * completes the callback only in the browser that holds it.\n */\n readonly state: string\n readonly expiresAt: Date\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 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 /** Every OIDC sign-in sets the name and picture the provider sends, so the strategy says which. */\n providerProfileFields(identity: UserIdentityRecord): readonly ProfileField[]\n}\n\nexport interface InviteUserInput {\n readonly email: string\n readonly groups?: readonly GroupDefinition[]\n readonly groupIds?: readonly string[]\n readonly expiresAt?: Date\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 readonly serviceAccounts: boolean\n}\n\nexport interface GetMembershipOptionsResult {\n /** Groups the caller may assign to a member (the `assignGroups` scope). */\n readonly groups: readonly InvitationGroupOption[]\n /** Groups the caller may place a service account in (the `serviceAccounts` scope). */\n readonly serviceAccountGroups: 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 /**\n * The groups among `groupIds` that the identity provider manages. They sync at the user's next\n * sign-in, so they cannot be removed here.\n */\n readonly managedGroupIds: 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 readonly managedGroupIds: 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 readonly managedGroupIds: 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 readonly managedGroupIds: readonly string[]\n}\n\n/** The signed-in person's own profile. */\nexport interface OwnProfile {\n readonly profile: UserProfile\n /** The fields their identity provider sets at sign-in, which they cannot edit here. */\n readonly managedFields: readonly ProfileField[]\n}\n\n/** Omitted fields stay unchanged, and `null` clears one. */\nexport interface UpdateOwnProfileInput {\n readonly displayName?: string | null\n readonly avatarUrl?: string | null\n}\n\n/** `\"session\"` reads only the cookie; `\"any\"` reads a bearer access token, else the cookie. */\nexport type AuthCredentialSource = \"session\" | \"any\"\n\nexport interface AuthSessionResolutionOptions {\n readonly credentialSource?: AuthCredentialSource\n /** Marks this request as eligible to renew a near-expiry browser session. */\n readonly sessionActivity?: \"foreground\"\n}\n\n/** Where an invitation link sends its recipient. */\nexport interface InvitationDestination {\n readonly requestOrigin: string\n readonly returnTo: string\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_cookie\"\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"
|
|
44
|
+
],
|
|
45
|
+
"mappings": "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",
|
|
46
|
+
"debugId": "86A4C82302343CA464756E2164756E21",
|
|
47
|
+
"names": []
|
|
48
|
+
}
|