@jini-ai/cms 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +84 -0
- package/dist/content-types/agent-tools.d.ts +65 -0
- package/dist/content-types/agent-tools.d.ts.map +1 -0
- package/dist/content-types/agent-tools.js +172 -0
- package/dist/content-types/agent-tools.js.map +1 -0
- package/dist/content-types/cleanup.d.ts +118 -0
- package/dist/content-types/cleanup.d.ts.map +1 -0
- package/dist/content-types/cleanup.js +65 -0
- package/dist/content-types/cleanup.js.map +1 -0
- package/dist/content-types/errors.d.ts +90 -0
- package/dist/content-types/errors.d.ts.map +1 -0
- package/dist/content-types/errors.js +119 -0
- package/dist/content-types/errors.js.map +1 -0
- package/dist/content-types/field-defs.d.ts +25 -0
- package/dist/content-types/field-defs.d.ts.map +1 -0
- package/dist/content-types/field-defs.js +155 -0
- package/dist/content-types/field-defs.js.map +1 -0
- package/dist/content-types/index-provisioning.d.ts +94 -0
- package/dist/content-types/index-provisioning.d.ts.map +1 -0
- package/dist/content-types/index-provisioning.js +133 -0
- package/dist/content-types/index-provisioning.js.map +1 -0
- package/dist/content-types/index.d.ts +63 -0
- package/dist/content-types/index.d.ts.map +1 -0
- package/dist/content-types/index.js +36 -0
- package/dist/content-types/index.js.map +1 -0
- package/dist/content-types/lifecycle-dispatch.d.ts +38 -0
- package/dist/content-types/lifecycle-dispatch.d.ts.map +1 -0
- package/dist/content-types/lifecycle-dispatch.js +28 -0
- package/dist/content-types/lifecycle-dispatch.js.map +1 -0
- package/dist/content-types/lifecycle.d.ts +104 -0
- package/dist/content-types/lifecycle.d.ts.map +1 -0
- package/dist/content-types/lifecycle.js +143 -0
- package/dist/content-types/lifecycle.js.map +1 -0
- package/dist/content-types/list.d.ts +44 -0
- package/dist/content-types/list.d.ts.map +1 -0
- package/dist/content-types/list.js +13 -0
- package/dist/content-types/list.js.map +1 -0
- package/dist/content-types/repo.memory.d.ts +72 -0
- package/dist/content-types/repo.memory.d.ts.map +1 -0
- package/dist/content-types/repo.memory.js +71 -0
- package/dist/content-types/repo.memory.js.map +1 -0
- package/dist/content-types/tool-registrations.d.ts +65 -0
- package/dist/content-types/tool-registrations.d.ts.map +1 -0
- package/dist/content-types/tool-registrations.js +180 -0
- package/dist/content-types/tool-registrations.js.map +1 -0
- package/dist/content-types/types.d.ts +78 -0
- package/dist/content-types/types.d.ts.map +1 -0
- package/dist/content-types/types.js +32 -0
- package/dist/content-types/types.js.map +1 -0
- package/dist/content-types/write-service.d.ts +141 -0
- package/dist/content-types/write-service.d.ts.map +1 -0
- package/dist/content-types/write-service.js +180 -0
- package/dist/content-types/write-service.js.map +1 -0
- package/dist/core/commands/change-set.d.ts +98 -0
- package/dist/core/commands/change-set.d.ts.map +1 -0
- package/dist/core/commands/change-set.js +2 -0
- package/dist/core/commands/change-set.js.map +1 -0
- package/dist/core/commands/command.d.ts +168 -0
- package/dist/core/commands/command.d.ts.map +1 -0
- package/dist/core/commands/command.js +173 -0
- package/dist/core/commands/command.js.map +1 -0
- package/dist/core/index.d.ts +45 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +43 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/ports.d.ts +139 -0
- package/dist/core/ports.d.ts.map +1 -0
- package/dist/core/ports.js +2 -0
- package/dist/core/ports.js.map +1 -0
- package/dist/core/tools/registration-kit.d.ts +308 -0
- package/dist/core/tools/registration-kit.d.ts.map +1 -0
- package/dist/core/tools/registration-kit.js +381 -0
- package/dist/core/tools/registration-kit.js.map +1 -0
- package/dist/entries/agent-tools.d.ts +78 -0
- package/dist/entries/agent-tools.d.ts.map +1 -0
- package/dist/entries/agent-tools.js +158 -0
- package/dist/entries/agent-tools.js.map +1 -0
- package/dist/entries/errors.d.ts +43 -0
- package/dist/entries/errors.d.ts.map +1 -0
- package/dist/entries/errors.js +59 -0
- package/dist/entries/errors.js.map +1 -0
- package/dist/entries/field-validation.d.ts +70 -0
- package/dist/entries/field-validation.d.ts.map +1 -0
- package/dist/entries/field-validation.js +87 -0
- package/dist/entries/field-validation.js.map +1 -0
- package/dist/entries/index.d.ts +55 -0
- package/dist/entries/index.d.ts.map +1 -0
- package/dist/entries/index.js +38 -0
- package/dist/entries/index.js.map +1 -0
- package/dist/entries/lifecycle-dispatch.d.ts +15 -0
- package/dist/entries/lifecycle-dispatch.d.ts.map +1 -0
- package/dist/entries/lifecycle-dispatch.js +16 -0
- package/dist/entries/lifecycle-dispatch.js.map +1 -0
- package/dist/entries/list.d.ts +47 -0
- package/dist/entries/list.d.ts.map +1 -0
- package/dist/entries/list.js +12 -0
- package/dist/entries/list.js.map +1 -0
- package/dist/entries/repo.memory.d.ts +64 -0
- package/dist/entries/repo.memory.d.ts.map +1 -0
- package/dist/entries/repo.memory.js +73 -0
- package/dist/entries/repo.memory.js.map +1 -0
- package/dist/entries/tool-registrations.d.ts +52 -0
- package/dist/entries/tool-registrations.d.ts.map +1 -0
- package/dist/entries/tool-registrations.js +141 -0
- package/dist/entries/tool-registrations.js.map +1 -0
- package/dist/entries/types.d.ts +55 -0
- package/dist/entries/types.d.ts.map +1 -0
- package/dist/entries/types.js +2 -0
- package/dist/entries/types.js.map +1 -0
- package/dist/entries/write-service.d.ts +202 -0
- package/dist/entries/write-service.d.ts.map +1 -0
- package/dist/entries/write-service.js +204 -0
- package/dist/entries/write-service.js.map +1 -0
- package/dist/identity/admin-crud-service.d.ts +252 -0
- package/dist/identity/admin-crud-service.d.ts.map +1 -0
- package/dist/identity/admin-crud-service.js +437 -0
- package/dist/identity/admin-crud-service.js.map +1 -0
- package/dist/identity/agent-tool-input.d.ts +58 -0
- package/dist/identity/agent-tool-input.d.ts.map +1 -0
- package/dist/identity/agent-tool-input.js +126 -0
- package/dist/identity/agent-tool-input.js.map +1 -0
- package/dist/identity/agent-tools.d.ts +101 -0
- package/dist/identity/agent-tools.d.ts.map +1 -0
- package/dist/identity/agent-tools.js +290 -0
- package/dist/identity/agent-tools.js.map +1 -0
- package/dist/identity/auth-service.d.ts +87 -0
- package/dist/identity/auth-service.d.ts.map +1 -0
- package/dist/identity/auth-service.js +141 -0
- package/dist/identity/auth-service.js.map +1 -0
- package/dist/identity/authorize.d.ts +90 -0
- package/dist/identity/authorize.d.ts.map +1 -0
- package/dist/identity/authorize.js +94 -0
- package/dist/identity/authorize.js.map +1 -0
- package/dist/identity/grant-service.d.ts +198 -0
- package/dist/identity/grant-service.d.ts.map +1 -0
- package/dist/identity/grant-service.js +361 -0
- package/dist/identity/grant-service.js.map +1 -0
- package/dist/identity/hasher.d.ts +39 -0
- package/dist/identity/hasher.d.ts.map +1 -0
- package/dist/identity/hasher.js +39 -0
- package/dist/identity/hasher.js.map +1 -0
- package/dist/identity/index.d.ts +59 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +51 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/password-policy.d.ts +58 -0
- package/dist/identity/password-policy.d.ts.map +1 -0
- package/dist/identity/password-policy.js +67 -0
- package/dist/identity/password-policy.js.map +1 -0
- package/dist/identity/permission-migrations.d.ts +86 -0
- package/dist/identity/permission-migrations.d.ts.map +1 -0
- package/dist/identity/permission-migrations.js +67 -0
- package/dist/identity/permission-migrations.js.map +1 -0
- package/dist/identity/permissions.d.ts +35 -0
- package/dist/identity/permissions.d.ts.map +1 -0
- package/dist/identity/permissions.js +603 -0
- package/dist/identity/permissions.js.map +1 -0
- package/dist/identity/ports.d.ts +201 -0
- package/dist/identity/ports.d.ts.map +1 -0
- package/dist/identity/ports.js +2 -0
- package/dist/identity/ports.js.map +1 -0
- package/dist/identity/repo.memory.d.ts +164 -0
- package/dist/identity/repo.memory.d.ts.map +1 -0
- package/dist/identity/repo.memory.js +224 -0
- package/dist/identity/repo.memory.js.map +1 -0
- package/dist/identity/seed.d.ts +42 -0
- package/dist/identity/seed.d.ts.map +1 -0
- package/dist/identity/seed.js +277 -0
- package/dist/identity/seed.js.map +1 -0
- package/dist/identity/tool-registrations.d.ts +50 -0
- package/dist/identity/tool-registrations.d.ts.map +1 -0
- package/dist/identity/tool-registrations.js +419 -0
- package/dist/identity/tool-registrations.js.map +1 -0
- package/dist/identity/types.d.ts +185 -0
- package/dist/identity/types.d.ts.map +1 -0
- package/dist/identity/types.js +64 -0
- package/dist/identity/types.js.map +1 -0
- package/dist/identity/username.d.ts +12 -0
- package/dist/identity/username.d.ts.map +1 -0
- package/dist/identity/username.js +14 -0
- package/dist/identity/username.js.map +1 -0
- package/dist/media/agent-tools.d.ts +66 -0
- package/dist/media/agent-tools.d.ts.map +1 -0
- package/dist/media/agent-tools.js +131 -0
- package/dist/media/agent-tools.js.map +1 -0
- package/dist/media/blob-gc-lock.d.ts +37 -0
- package/dist/media/blob-gc-lock.d.ts.map +1 -0
- package/dist/media/blob-gc-lock.js +55 -0
- package/dist/media/blob-gc-lock.js.map +1 -0
- package/dist/media/blob-gc.d.ts +246 -0
- package/dist/media/blob-gc.d.ts.map +1 -0
- package/dist/media/blob-gc.js +254 -0
- package/dist/media/blob-gc.js.map +1 -0
- package/dist/media/blob-key.d.ts +28 -0
- package/dist/media/blob-key.d.ts.map +1 -0
- package/dist/media/blob-key.js +11 -0
- package/dist/media/blob-key.js.map +1 -0
- package/dist/media/blob-store.fs.d.ts +23 -0
- package/dist/media/blob-store.fs.d.ts.map +1 -0
- package/dist/media/blob-store.fs.js +48 -0
- package/dist/media/blob-store.fs.js.map +1 -0
- package/dist/media/blob-store.memory.d.ts +22 -0
- package/dist/media/blob-store.memory.d.ts.map +1 -0
- package/dist/media/blob-store.memory.js +23 -0
- package/dist/media/blob-store.memory.js.map +1 -0
- package/dist/media/content-type-sniffer.d.ts +49 -0
- package/dist/media/content-type-sniffer.d.ts.map +1 -0
- package/dist/media/content-type-sniffer.js +141 -0
- package/dist/media/content-type-sniffer.js.map +1 -0
- package/dist/media/image-transformer.d.ts +45 -0
- package/dist/media/image-transformer.d.ts.map +1 -0
- package/dist/media/image-transformer.js +23 -0
- package/dist/media/image-transformer.js.map +1 -0
- package/dist/media/image-transformer.sharp.d.ts +26 -0
- package/dist/media/image-transformer.sharp.d.ts.map +1 -0
- package/dist/media/image-transformer.sharp.js +91 -0
- package/dist/media/image-transformer.sharp.js.map +1 -0
- package/dist/media/index.d.ts +43 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/index.js +31 -0
- package/dist/media/index.js.map +1 -0
- package/dist/media/media-service.d.ts +244 -0
- package/dist/media/media-service.d.ts.map +1 -0
- package/dist/media/media-service.js +345 -0
- package/dist/media/media-service.js.map +1 -0
- package/dist/media/ports.d.ts +142 -0
- package/dist/media/ports.d.ts.map +1 -0
- package/dist/media/ports.js +2 -0
- package/dist/media/ports.js.map +1 -0
- package/dist/media/rendition-service.d.ts +66 -0
- package/dist/media/rendition-service.d.ts.map +1 -0
- package/dist/media/rendition-service.js +135 -0
- package/dist/media/rendition-service.js.map +1 -0
- package/dist/media/repo.memory.d.ts +107 -0
- package/dist/media/repo.memory.d.ts.map +1 -0
- package/dist/media/repo.memory.js +131 -0
- package/dist/media/repo.memory.js.map +1 -0
- package/dist/media/tool-registrations.d.ts +42 -0
- package/dist/media/tool-registrations.d.ts.map +1 -0
- package/dist/media/tool-registrations.js +121 -0
- package/dist/media/tool-registrations.js.map +1 -0
- package/dist/media/transform-lock.d.ts +36 -0
- package/dist/media/transform-lock.d.ts.map +1 -0
- package/dist/media/transform-lock.js +50 -0
- package/dist/media/transform-lock.js.map +1 -0
- package/dist/media/transform-registry.d.ts +103 -0
- package/dist/media/transform-registry.d.ts.map +1 -0
- package/dist/media/transform-registry.js +87 -0
- package/dist/media/transform-registry.js.map +1 -0
- package/dist/media/transform-types.d.ts +82 -0
- package/dist/media/transform-types.d.ts.map +1 -0
- package/dist/media/transform-types.js +47 -0
- package/dist/media/transform-types.js.map +1 -0
- package/dist/media/types.d.ts +150 -0
- package/dist/media/types.d.ts.map +1 -0
- package/dist/media/types.js +26 -0
- package/dist/media/types.js.map +1 -0
- package/dist/navigation/agent-tools.d.ts +90 -0
- package/dist/navigation/agent-tools.d.ts.map +1 -0
- package/dist/navigation/agent-tools.js +225 -0
- package/dist/navigation/agent-tools.js.map +1 -0
- package/dist/navigation/contracts.d.ts +98 -0
- package/dist/navigation/contracts.d.ts.map +1 -0
- package/dist/navigation/contracts.js +70 -0
- package/dist/navigation/contracts.js.map +1 -0
- package/dist/navigation/index.d.ts +39 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +30 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/navigation/menu-service.d.ts +256 -0
- package/dist/navigation/menu-service.d.ts.map +1 -0
- package/dist/navigation/menu-service.js +382 -0
- package/dist/navigation/menu-service.js.map +1 -0
- package/dist/navigation/ports.d.ts +147 -0
- package/dist/navigation/ports.d.ts.map +1 -0
- package/dist/navigation/ports.js +2 -0
- package/dist/navigation/ports.js.map +1 -0
- package/dist/navigation/read-model.d.ts +11 -0
- package/dist/navigation/read-model.d.ts.map +1 -0
- package/dist/navigation/read-model.js +27 -0
- package/dist/navigation/read-model.js.map +1 -0
- package/dist/navigation/reconcile.d.ts +57 -0
- package/dist/navigation/reconcile.d.ts.map +1 -0
- package/dist/navigation/reconcile.js +33 -0
- package/dist/navigation/reconcile.js.map +1 -0
- package/dist/navigation/repo.memory.d.ts +137 -0
- package/dist/navigation/repo.memory.d.ts.map +1 -0
- package/dist/navigation/repo.memory.js +95 -0
- package/dist/navigation/repo.memory.js.map +1 -0
- package/dist/navigation/resolver.d.ts +110 -0
- package/dist/navigation/resolver.d.ts.map +1 -0
- package/dist/navigation/resolver.js +131 -0
- package/dist/navigation/resolver.js.map +1 -0
- package/dist/navigation/tool-registrations.d.ts +43 -0
- package/dist/navigation/tool-registrations.d.ts.map +1 -0
- package/dist/navigation/tool-registrations.js +126 -0
- package/dist/navigation/tool-registrations.js.map +1 -0
- package/dist/navigation/types.d.ts +207 -0
- package/dist/navigation/types.d.ts.map +1 -0
- package/dist/navigation/types.js +14 -0
- package/dist/navigation/types.js.map +1 -0
- package/dist/presentation/index.d.ts +15 -0
- package/dist/presentation/index.d.ts.map +1 -0
- package/dist/presentation/index.js +15 -0
- package/dist/presentation/index.js.map +1 -0
- package/dist/presentation/presentation.d.ts +72 -0
- package/dist/presentation/presentation.d.ts.map +1 -0
- package/dist/presentation/presentation.js +51 -0
- package/dist/presentation/presentation.js.map +1 -0
- package/dist/presentation/repo.memory.d.ts +9 -0
- package/dist/presentation/repo.memory.d.ts.map +1 -0
- package/dist/presentation/repo.memory.js +21 -0
- package/dist/presentation/repo.memory.js.map +1 -0
- package/dist/server/index.d.ts +28 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +28 -0
- package/dist/server/index.js.map +1 -0
- package/dist/settings/agent-tools.d.ts +83 -0
- package/dist/settings/agent-tools.d.ts.map +1 -0
- package/dist/settings/agent-tools.js +200 -0
- package/dist/settings/agent-tools.js.map +1 -0
- package/dist/settings/agent-writable-preferences.d.ts +67 -0
- package/dist/settings/agent-writable-preferences.d.ts.map +1 -0
- package/dist/settings/agent-writable-preferences.js +144 -0
- package/dist/settings/agent-writable-preferences.js.map +1 -0
- package/dist/settings/change-feed.d.ts +74 -0
- package/dist/settings/change-feed.d.ts.map +1 -0
- package/dist/settings/change-feed.js +61 -0
- package/dist/settings/change-feed.js.map +1 -0
- package/dist/settings/definitions-dispatch.d.ts +51 -0
- package/dist/settings/definitions-dispatch.d.ts.map +1 -0
- package/dist/settings/definitions-dispatch.js +86 -0
- package/dist/settings/definitions-dispatch.js.map +1 -0
- package/dist/settings/dictionaries/index.d.ts +45 -0
- package/dist/settings/dictionaries/index.d.ts.map +1 -0
- package/dist/settings/dictionaries/index.js +69 -0
- package/dist/settings/dictionaries/index.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ar.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ar.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ar.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.ar.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.bn.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.bn.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.bn.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.bn.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.de.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.de.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.de.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.de.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.es.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.es.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.es.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.es.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.fa.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.fa.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.fa.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.fa.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.fr.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.fr.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.fr.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.fr.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.hi.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.hi.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.hi.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.hi.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.hu.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.hu.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.hu.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.hu.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.id.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.id.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.id.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.id.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.it.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.it.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.it.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.it.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ja.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ja.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ja.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.ja.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ko.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ko.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ko.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.ko.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.pl.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.pl.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.pl.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.pl.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.pt-BR.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.pt-BR.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.pt-BR.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.pt-BR.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ru.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ru.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ru.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.ru.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.th.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.th.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.th.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.th.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.tr.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.tr.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.tr.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.tr.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.uk.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.uk.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.uk.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.uk.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ur.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ur.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ur.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.ur.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.zh-CN.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.zh-CN.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.zh-CN.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.zh-CN.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.zh-TW.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.zh-TW.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.zh-TW.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.zh-TW.js.map +1 -0
- package/dist/settings/ensure-definitions.d.ts +88 -0
- package/dist/settings/ensure-definitions.d.ts.map +1 -0
- package/dist/settings/ensure-definitions.js +91 -0
- package/dist/settings/ensure-definitions.js.map +1 -0
- package/dist/settings/errors.d.ts +36 -0
- package/dist/settings/errors.d.ts.map +1 -0
- package/dist/settings/errors.js +40 -0
- package/dist/settings/errors.js.map +1 -0
- package/dist/settings/index.d.ts +37 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +36 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/settings/ports.d.ts +117 -0
- package/dist/settings/ports.d.ts.map +1 -0
- package/dist/settings/ports.js +2 -0
- package/dist/settings/ports.js.map +1 -0
- package/dist/settings/purge-service.d.ts +53 -0
- package/dist/settings/purge-service.d.ts.map +1 -0
- package/dist/settings/purge-service.js +105 -0
- package/dist/settings/purge-service.js.map +1 -0
- package/dist/settings/repo.memory.d.ts +119 -0
- package/dist/settings/repo.memory.d.ts.map +1 -0
- package/dist/settings/repo.memory.js +199 -0
- package/dist/settings/repo.memory.js.map +1 -0
- package/dist/settings/settings.d.ts +124 -0
- package/dist/settings/settings.d.ts.map +1 -0
- package/dist/settings/settings.js +238 -0
- package/dist/settings/settings.js.map +1 -0
- package/dist/settings/tool-registrations.d.ts +56 -0
- package/dist/settings/tool-registrations.d.ts.map +1 -0
- package/dist/settings/tool-registrations.js +240 -0
- package/dist/settings/tool-registrations.js.map +1 -0
- package/dist/settings/types.d.ts +125 -0
- package/dist/settings/types.d.ts.map +1 -0
- package/dist/settings/types.js +3 -0
- package/dist/settings/types.js.map +1 -0
- package/dist/settings/ui-tab-definitions.d.ts +41 -0
- package/dist/settings/ui-tab-definitions.d.ts.map +1 -0
- package/dist/settings/ui-tab-definitions.js +148 -0
- package/dist/settings/ui-tab-definitions.js.map +1 -0
- package/dist/settings/write-service.d.ts +314 -0
- package/dist/settings/write-service.d.ts.map +1 -0
- package/dist/settings/write-service.js +677 -0
- package/dist/settings/write-service.js.map +1 -0
- package/dist/taxonomy/agent-tools.d.ts +76 -0
- package/dist/taxonomy/agent-tools.d.ts.map +1 -0
- package/dist/taxonomy/agent-tools.js +178 -0
- package/dist/taxonomy/agent-tools.js.map +1 -0
- package/dist/taxonomy/content-lookup.d.ts +45 -0
- package/dist/taxonomy/content-lookup.d.ts.map +1 -0
- package/dist/taxonomy/content-lookup.js +9 -0
- package/dist/taxonomy/content-lookup.js.map +1 -0
- package/dist/taxonomy/index.d.ts +38 -0
- package/dist/taxonomy/index.d.ts.map +1 -0
- package/dist/taxonomy/index.js +38 -0
- package/dist/taxonomy/index.js.map +1 -0
- package/dist/taxonomy/list.d.ts +39 -0
- package/dist/taxonomy/list.d.ts.map +1 -0
- package/dist/taxonomy/list.js +19 -0
- package/dist/taxonomy/list.js.map +1 -0
- package/dist/taxonomy/merge-term.d.ts +94 -0
- package/dist/taxonomy/merge-term.d.ts.map +1 -0
- package/dist/taxonomy/merge-term.js +65 -0
- package/dist/taxonomy/merge-term.js.map +1 -0
- package/dist/taxonomy/repo.memory.d.ts +160 -0
- package/dist/taxonomy/repo.memory.d.ts.map +1 -0
- package/dist/taxonomy/repo.memory.js +171 -0
- package/dist/taxonomy/repo.memory.js.map +1 -0
- package/dist/taxonomy/validation-chain.d.ts +114 -0
- package/dist/taxonomy/validation-chain.d.ts.map +1 -0
- package/dist/taxonomy/validation-chain.js +152 -0
- package/dist/taxonomy/validation-chain.js.map +1 -0
- package/dist/taxonomy/write-service.d.ts +387 -0
- package/dist/taxonomy/write-service.d.ts.map +1 -0
- package/dist/taxonomy/write-service.js +350 -0
- package/dist/taxonomy/write-service.js.map +1 -0
- package/dist/workspace/agent-tools.d.ts +67 -0
- package/dist/workspace/agent-tools.d.ts.map +1 -0
- package/dist/workspace/agent-tools.js +103 -0
- package/dist/workspace/agent-tools.js.map +1 -0
- package/dist/workspace/create.d.ts +116 -0
- package/dist/workspace/create.d.ts.map +1 -0
- package/dist/workspace/create.js +69 -0
- package/dist/workspace/create.js.map +1 -0
- package/dist/workspace/delete.d.ts +50 -0
- package/dist/workspace/delete.d.ts.map +1 -0
- package/dist/workspace/delete.js +24 -0
- package/dist/workspace/delete.js.map +1 -0
- package/dist/workspace/index.d.ts +27 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +27 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace/repo.memory.d.ts +34 -0
- package/dist/workspace/repo.memory.d.ts.map +1 -0
- package/dist/workspace/repo.memory.js +50 -0
- package/dist/workspace/repo.memory.js.map +1 -0
- package/dist/workspace/tool-registrations.d.ts +38 -0
- package/dist/workspace/tool-registrations.d.ts.map +1 -0
- package/dist/workspace/tool-registrations.js +71 -0
- package/dist/workspace/tool-registrations.js.map +1 -0
- package/dist/workspace/update.d.ts +52 -0
- package/dist/workspace/update.d.ts.map +1 -0
- package/dist/workspace/update.js +41 -0
- package/dist/workspace/update.js.map +1 -0
- package/package.json +149 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { authorize, resolveEffectivePermissions } from "./authorize.js";
|
|
2
|
+
import { GrantExceedsIssuerError, IdentityConflictError, IdentityForbiddenError, IdentityNotFoundError, IdentityValidationError, } from "./types.js";
|
|
3
|
+
import { normalizeUsername } from "./username.js";
|
|
4
|
+
import { validatePasswordPolicy } from "./password-policy.js";
|
|
5
|
+
/**
|
|
6
|
+
* @file Human grant-writing transitions (state.spec.md §3): `CREATE_USER`,
|
|
7
|
+
* `CREATE_ROLE`, `CREATE_POLICY`, `ASSIGN_ROLE`, `ATTACH_POLICY`.
|
|
8
|
+
*
|
|
9
|
+
* Purpose:
|
|
10
|
+
* The only usable identity principal before this file was the seeded owner —
|
|
11
|
+
* there was no API path to create a second user or grant/change permissions.
|
|
12
|
+
* These five functions are that path, following `auth-service.ts`'s exact
|
|
13
|
+
* shape (`{ deps: AuthServiceDeps, input: {...} }`, one exported async
|
|
14
|
+
* function per transition, plain `Error` subclasses for control flow).
|
|
15
|
+
*
|
|
16
|
+
* Out of scope (deferred, see the dispatch directive): `ISSUE_API_KEY`,
|
|
17
|
+
* `CREATE_PRINCIPAL` (api_key/agent principal creation), agent/api_key
|
|
18
|
+
* delegation, `WRITE_POLICY_PERMISSION`, `DISABLE_PRINCIPAL`.
|
|
19
|
+
*
|
|
20
|
+
* Architectural role:
|
|
21
|
+
* Ordinary core functions, not ports (mirrors `auth-service.ts`'s reasoning —
|
|
22
|
+
* grant-writing logic has one implementation). Each function calls
|
|
23
|
+
* `authorize()`/`resolveEffectivePermissions()` from `authorize.ts` itself
|
|
24
|
+
* (rather than pushing the gate into the route layer, the way
|
|
25
|
+
* `members/disable.ts`'s route does) so the caller-permission gate and the
|
|
26
|
+
* INV-07 clamp are exercised directly by unit tests, no HTTP harness needed.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Assemble the `AuthorizeDeps` bag `authorize()`/`resolveEffectivePermissions()` expect from the
|
|
30
|
+
* flat `IdentityRepos` bag. Exported so `admin-crud-service.ts`'s new transitions
|
|
31
|
+
* (`ENABLE_PRINCIPAL`/`UPDATE_USER`/`RESET_USER_PASSWORD`/`UPDATE_ROLE`/`UPDATE_POLICY`/
|
|
32
|
+
* `DELETE_ROLE`/`DELETE_POLICY`/`WRITE_POLICY_PERMISSION`/`DISABLE_PRINCIPAL`) reuse the identical
|
|
33
|
+
* gate/clamp logic rather than duplicating it — same file-split reasoning `auth-service.ts` and
|
|
34
|
+
* `grant-service.ts` already use (one shared helper set, two transition files).
|
|
35
|
+
*/
|
|
36
|
+
export function authorizeDepsFrom(repos) {
|
|
37
|
+
return {
|
|
38
|
+
principals: repos.principals,
|
|
39
|
+
principalRoles: repos.principalRoles,
|
|
40
|
+
rolePolicies: repos.rolePolicies,
|
|
41
|
+
principalPolicies: repos.principalPolicies,
|
|
42
|
+
policyPermissions: repos.policyPermissions,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Fail-closed caller-permission gate shared by every transition in this file.
|
|
47
|
+
* Throws `IdentityForbiddenError` (403 `FORBIDDEN`) unless the caller holds
|
|
48
|
+
* at least one of `permissions` (an OR gate — `CREATE_USER` accepts either
|
|
49
|
+
* `user.manage` or `member.manage`, state.spec §3).
|
|
50
|
+
*
|
|
51
|
+
* @complexity O(p) `authorize()` calls, p = `permissions.length` (1 or 2 in
|
|
52
|
+
* every caller this pass) — each itself O(resolveEffectivePermissions), see
|
|
53
|
+
* that function's doc.
|
|
54
|
+
* @overallScore 100
|
|
55
|
+
*/
|
|
56
|
+
export async function assertCallerHasAnyPermission(required) {
|
|
57
|
+
const { deps, workspaceId, callerPrincipalId, permissions } = required;
|
|
58
|
+
let lastReason = "no_grant";
|
|
59
|
+
for (const permission of permissions) {
|
|
60
|
+
const result = await authorize({
|
|
61
|
+
deps: authorizeDepsFrom(deps.repos),
|
|
62
|
+
principalId: callerPrincipalId,
|
|
63
|
+
permission,
|
|
64
|
+
context: { workspaceId },
|
|
65
|
+
});
|
|
66
|
+
if (result.allowed)
|
|
67
|
+
return;
|
|
68
|
+
lastReason = result.reason;
|
|
69
|
+
}
|
|
70
|
+
throw new IdentityForbiddenError(`principal '${callerPrincipalId}' is not authorized for any of [${permissions.join(", ")}]`, permissions.join("|"), lastReason);
|
|
71
|
+
}
|
|
72
|
+
/** True iff `effectiveRows` contains an unconstrained hold of `permission` — an exact match with
|
|
73
|
+
* `resourceType`/`constraintJson` both null, or the owner wildcard `*` (which counts as an
|
|
74
|
+
* unconstrained hold of every permission, INV-07). */
|
|
75
|
+
function holdsUnconstrained(effectiveRows, permission) {
|
|
76
|
+
const hasWildcard = effectiveRows.some((row) => row.permission === "*" && row.resourceType == null && row.constraintJson == null);
|
|
77
|
+
if (hasWildcard)
|
|
78
|
+
return true;
|
|
79
|
+
return effectiveRows.some((row) => row.permission === permission && row.resourceType == null && row.constraintJson == null);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The INV-07 grant-authority clamp (feature.spec.md, state.spec §3
|
|
83
|
+
* `ASSIGN_ROLE`/`ATTACH_POLICY` rows): every permission in `conferredPermissions`
|
|
84
|
+
* must be a matching effective row the caller holds unconstrained
|
|
85
|
+
* (`resourceType`/`constraintJson` both null; owner's `*` qualifies for all).
|
|
86
|
+
* A permission held only conditionally (resource-scoped or constraint-bound)
|
|
87
|
+
* cannot be delegated. Throws `GrantExceedsIssuerError` (403
|
|
88
|
+
* `GRANT_EXCEEDS_ISSUER`) naming every offending permission, and writes no
|
|
89
|
+
* grant row (caller does the write only after this resolves).
|
|
90
|
+
*
|
|
91
|
+
* @complexity O(resolveEffectivePermissions) + O(k) local filtering, k =
|
|
92
|
+
* `conferredPermissions.length` (bounded by one role's/policy's permission
|
|
93
|
+
* rows — a handful, per `identity/INFO.md`'s scale assumptions).
|
|
94
|
+
* @overallScore 100
|
|
95
|
+
*/
|
|
96
|
+
export async function assertGrantClamp(required) {
|
|
97
|
+
const { deps, workspaceId, callerPrincipalId, conferredPermissions } = required;
|
|
98
|
+
const distinctPermissions = [...new Set(conferredPermissions)];
|
|
99
|
+
if (distinctPermissions.length === 0)
|
|
100
|
+
return;
|
|
101
|
+
const effectiveRows = await resolveEffectivePermissions({
|
|
102
|
+
deps: authorizeDepsFrom(deps.repos),
|
|
103
|
+
principalId: callerPrincipalId,
|
|
104
|
+
workspaceId,
|
|
105
|
+
});
|
|
106
|
+
const offendingPermissions = distinctPermissions.filter((permission) => !holdsUnconstrained(effectiveRows, permission));
|
|
107
|
+
if (offendingPermissions.length > 0) {
|
|
108
|
+
throw new GrantExceedsIssuerError(`principal '${callerPrincipalId}' cannot grant permission(s) it does not hold unconstrained: ${offendingPermissions.join(", ")}`, offendingPermissions);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* `ASSIGN_ROLE`/`ATTACH_POLICY`'s shared human-target-only rule (AC-25b):
|
|
113
|
+
* machine (`api_key`/`system`) principal authority is set solely at
|
|
114
|
+
* issuance, never mutated by a later human-grant transition. Throws
|
|
115
|
+
* `IdentityValidationError` (400 `VALIDATION_ERROR`) for a non-`user` or
|
|
116
|
+
* missing target — this check runs *before* the INV-07 clamp (AC-25's note:
|
|
117
|
+
* "does not reach this clamp").
|
|
118
|
+
*/
|
|
119
|
+
async function findAssignableTargetOrThrow(required) {
|
|
120
|
+
const { deps, workspaceId, principalId, transitionName } = required;
|
|
121
|
+
const target = await deps.repos.principals.findById({ workspaceId, id: principalId });
|
|
122
|
+
if (!target) {
|
|
123
|
+
throw new IdentityNotFoundError(`principal '${principalId}' was not found`);
|
|
124
|
+
}
|
|
125
|
+
if (target.kind !== "user") {
|
|
126
|
+
throw new IdentityValidationError(`${transitionName} target must be a human (kind='user') principal, got kind='${target.kind}'`);
|
|
127
|
+
}
|
|
128
|
+
return target;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* `CREATE_USER` (state.spec §3, REQ-01/MF-1). Atomically mints a NEW
|
|
132
|
+
* `kind='user'` principal and its `users` row — the `principalId` is always
|
|
133
|
+
* generated here, never caller-supplied, so this transition can never attach
|
|
134
|
+
* a credential to a pre-existing principal (the MF-1 privilege-escalation
|
|
135
|
+
* class: an earlier draft let an admin bind a password to the seeded owner
|
|
136
|
+
* principal and log in as owner). Gated by `user.manage` OR `member.manage`
|
|
137
|
+
* (admin onboarding, AC-22).
|
|
138
|
+
*
|
|
139
|
+
* "Atomically" here means structurally, not via a DB transaction — the
|
|
140
|
+
* in-memory adapters have no cross-repo transaction (same disclosed gap as
|
|
141
|
+
* `seed.ts`/`executeCommand`'s compensating-rollback path). The invariant
|
|
142
|
+
* that actually matters (no credential ever attaches to an existing
|
|
143
|
+
* principal) holds regardless, because `principalId` is generated inline and
|
|
144
|
+
* the password is hashed before either row is written, so a hashing failure
|
|
145
|
+
* leaves no orphan principal. A future SQLite adapter wraps both writes in
|
|
146
|
+
* one real transaction (port/adapter rule-of-two) without changing this contract.
|
|
147
|
+
*
|
|
148
|
+
* @complexity O(1) — one permission check, one username lookup, one hash,
|
|
149
|
+
* two saves.
|
|
150
|
+
* @overallScore 100
|
|
151
|
+
*/
|
|
152
|
+
export async function createUser(required) {
|
|
153
|
+
const { deps, input } = required;
|
|
154
|
+
await assertCallerHasAnyPermission({
|
|
155
|
+
deps,
|
|
156
|
+
workspaceId: input.workspaceId,
|
|
157
|
+
callerPrincipalId: input.callerPrincipalId,
|
|
158
|
+
permissions: ["user.manage", "member.manage"],
|
|
159
|
+
});
|
|
160
|
+
const username = normalizeUsername(input.username ?? "");
|
|
161
|
+
if (!username || !input.password) {
|
|
162
|
+
throw new IdentityValidationError("username and password are required");
|
|
163
|
+
}
|
|
164
|
+
// NIST SP 800-63B length-only policy (MSG-04) — never reaches seed.ts's owner password, see
|
|
165
|
+
// password-policy.ts's own header for why that separation is deliberate.
|
|
166
|
+
const passwordError = validatePasswordPolicy(input.password);
|
|
167
|
+
if (passwordError) {
|
|
168
|
+
throw new IdentityValidationError(passwordError);
|
|
169
|
+
}
|
|
170
|
+
const existingUser = await deps.repos.users.findByUsername({ workspaceId: input.workspaceId, username });
|
|
171
|
+
if (existingUser) {
|
|
172
|
+
throw new IdentityConflictError(`username '${username}' is already in use`);
|
|
173
|
+
}
|
|
174
|
+
const passwordHash = await deps.hasher.hash(input.password);
|
|
175
|
+
const nowIso = deps.clock.nowIso();
|
|
176
|
+
const principalId = deps.idGen.newId();
|
|
177
|
+
const principal = {
|
|
178
|
+
id: principalId,
|
|
179
|
+
workspaceId: input.workspaceId,
|
|
180
|
+
kind: "user",
|
|
181
|
+
displayName: username,
|
|
182
|
+
status: "active",
|
|
183
|
+
createdAt: nowIso,
|
|
184
|
+
};
|
|
185
|
+
const user = {
|
|
186
|
+
principalId,
|
|
187
|
+
workspaceId: input.workspaceId,
|
|
188
|
+
username,
|
|
189
|
+
email: input.email,
|
|
190
|
+
passwordHash,
|
|
191
|
+
};
|
|
192
|
+
await deps.repos.principals.save(principal);
|
|
193
|
+
await deps.repos.users.save(user);
|
|
194
|
+
return { principal, user };
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* `CREATE_ROLE` (state.spec §3). Gated by `role.manage`. Always mints
|
|
198
|
+
* `isBuiltin=false` — built-ins are SEED-only and immutable (INV-06).
|
|
199
|
+
*
|
|
200
|
+
* Deviation from the state.spec §3 table (disclosed): that row lists
|
|
201
|
+
* `name`, `description?` jointly for `CREATE_ROLE`/`CREATE_POLICY`, but
|
|
202
|
+
* `RoleRecord` (types.ts, frozen before this task) has no `description`
|
|
203
|
+
* field — only `PolicyRecord` does. `createRole` therefore takes `name`
|
|
204
|
+
* only; `createPolicy` below takes both.
|
|
205
|
+
*
|
|
206
|
+
* @complexity O(1) — one permission check, one save.
|
|
207
|
+
* @overallScore 100
|
|
208
|
+
*/
|
|
209
|
+
export async function createRole(required) {
|
|
210
|
+
const { deps, input } = required;
|
|
211
|
+
await assertCallerHasAnyPermission({
|
|
212
|
+
deps,
|
|
213
|
+
workspaceId: input.workspaceId,
|
|
214
|
+
callerPrincipalId: input.callerPrincipalId,
|
|
215
|
+
permissions: ["role.manage"],
|
|
216
|
+
});
|
|
217
|
+
const name = (input.name ?? "").trim();
|
|
218
|
+
if (!name) {
|
|
219
|
+
throw new IdentityValidationError("role name is required");
|
|
220
|
+
}
|
|
221
|
+
const role = {
|
|
222
|
+
id: deps.idGen.newId(),
|
|
223
|
+
workspaceId: input.workspaceId,
|
|
224
|
+
name,
|
|
225
|
+
isBuiltin: false,
|
|
226
|
+
};
|
|
227
|
+
await deps.repos.roles.save(role);
|
|
228
|
+
return { role };
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* `CREATE_POLICY` (state.spec §3). Gated by `role.manage`. Always mints
|
|
232
|
+
* `isBuiltin=false` and `isFrozen=false` — only the (out-of-scope this pass)
|
|
233
|
+
* `ISSUE_API_KEY` transition ever mints `isFrozen=true` policies.
|
|
234
|
+
*
|
|
235
|
+
* @complexity O(1) — one permission check, one save.
|
|
236
|
+
* @overallScore 100
|
|
237
|
+
*/
|
|
238
|
+
export async function createPolicy(required) {
|
|
239
|
+
const { deps, input } = required;
|
|
240
|
+
await assertCallerHasAnyPermission({
|
|
241
|
+
deps,
|
|
242
|
+
workspaceId: input.workspaceId,
|
|
243
|
+
callerPrincipalId: input.callerPrincipalId,
|
|
244
|
+
permissions: ["role.manage"],
|
|
245
|
+
});
|
|
246
|
+
const name = (input.name ?? "").trim();
|
|
247
|
+
if (!name) {
|
|
248
|
+
throw new IdentityValidationError("policy name is required");
|
|
249
|
+
}
|
|
250
|
+
const policy = {
|
|
251
|
+
id: deps.idGen.newId(),
|
|
252
|
+
workspaceId: input.workspaceId,
|
|
253
|
+
name,
|
|
254
|
+
description: input.description,
|
|
255
|
+
isBuiltin: false,
|
|
256
|
+
isFrozen: false,
|
|
257
|
+
};
|
|
258
|
+
await deps.repos.policies.save(policy);
|
|
259
|
+
return { policy };
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* `ASSIGN_ROLE` (state.spec §3, REQ-02, AC-24/AC-25). Gated by `role.manage`;
|
|
263
|
+
* target must be a `kind='user'` principal (AC-25b); the INV-07 clamp must
|
|
264
|
+
* pass over every permission carried by the role's policies (AC-24) — so
|
|
265
|
+
* assigning the built-in `owner` role requires the caller to already hold
|
|
266
|
+
* the wildcard `*` (owner-only). No row is written on any rejection.
|
|
267
|
+
*
|
|
268
|
+
* @complexity O(resolveEffectivePermissions) + O(role's rolePolicy count)
|
|
269
|
+
* round trips to gather conferred permissions — both bounded by the small,
|
|
270
|
+
* hand-authored grant graph this system assumes (see `identity/INFO.md`).
|
|
271
|
+
* @overallScore 100
|
|
272
|
+
*/
|
|
273
|
+
export async function assignRole(required) {
|
|
274
|
+
const { deps, input } = required;
|
|
275
|
+
await assertCallerHasAnyPermission({
|
|
276
|
+
deps,
|
|
277
|
+
workspaceId: input.workspaceId,
|
|
278
|
+
callerPrincipalId: input.callerPrincipalId,
|
|
279
|
+
permissions: ["role.manage"],
|
|
280
|
+
});
|
|
281
|
+
await findAssignableTargetOrThrow({
|
|
282
|
+
deps,
|
|
283
|
+
workspaceId: input.workspaceId,
|
|
284
|
+
principalId: input.principalId,
|
|
285
|
+
transitionName: "ASSIGN_ROLE",
|
|
286
|
+
});
|
|
287
|
+
const role = await deps.repos.roles.findById({ workspaceId: input.workspaceId, id: input.roleId });
|
|
288
|
+
if (!role) {
|
|
289
|
+
throw new IdentityNotFoundError(`role '${input.roleId}' was not found`);
|
|
290
|
+
}
|
|
291
|
+
const rolePolicyLinks = await deps.repos.rolePolicies.listByRoleId({
|
|
292
|
+
workspaceId: input.workspaceId,
|
|
293
|
+
roleId: input.roleId,
|
|
294
|
+
});
|
|
295
|
+
const policyPermissionGroups = await Promise.all(rolePolicyLinks.map((link) => deps.repos.policyPermissions.listByPolicyId({ workspaceId: input.workspaceId, policyId: link.policyId })));
|
|
296
|
+
const conferredPermissions = policyPermissionGroups.flat().map((row) => row.permission);
|
|
297
|
+
await assertGrantClamp({
|
|
298
|
+
deps,
|
|
299
|
+
workspaceId: input.workspaceId,
|
|
300
|
+
callerPrincipalId: input.callerPrincipalId,
|
|
301
|
+
conferredPermissions,
|
|
302
|
+
});
|
|
303
|
+
const assignment = {
|
|
304
|
+
id: deps.idGen.newId(),
|
|
305
|
+
workspaceId: input.workspaceId,
|
|
306
|
+
principalId: input.principalId,
|
|
307
|
+
roleId: input.roleId,
|
|
308
|
+
};
|
|
309
|
+
await deps.repos.principalRoles.save(assignment);
|
|
310
|
+
return { assignment };
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* `ATTACH_POLICY` (state.spec §3, REQ-02, AC-24/AC-25). Gated by
|
|
314
|
+
* `role.manage`; target must be a `kind='user'` principal (AC-25b); the
|
|
315
|
+
* INV-07 clamp must pass over every permission the policy carries (AC-24) —
|
|
316
|
+
* attaching the built-in `owner` policy requires the caller to already hold
|
|
317
|
+
* `*` (owner-only). No row is written on any rejection.
|
|
318
|
+
*
|
|
319
|
+
* @complexity O(resolveEffectivePermissions) + O(policy's permission row
|
|
320
|
+
* count) — both bounded, see `assignRole`'s doc.
|
|
321
|
+
* @overallScore 100
|
|
322
|
+
*/
|
|
323
|
+
export async function attachPolicy(required) {
|
|
324
|
+
const { deps, input } = required;
|
|
325
|
+
await assertCallerHasAnyPermission({
|
|
326
|
+
deps,
|
|
327
|
+
workspaceId: input.workspaceId,
|
|
328
|
+
callerPrincipalId: input.callerPrincipalId,
|
|
329
|
+
permissions: ["role.manage"],
|
|
330
|
+
});
|
|
331
|
+
await findAssignableTargetOrThrow({
|
|
332
|
+
deps,
|
|
333
|
+
workspaceId: input.workspaceId,
|
|
334
|
+
principalId: input.principalId,
|
|
335
|
+
transitionName: "ATTACH_POLICY",
|
|
336
|
+
});
|
|
337
|
+
const policy = await deps.repos.policies.findById({ workspaceId: input.workspaceId, id: input.policyId });
|
|
338
|
+
if (!policy) {
|
|
339
|
+
throw new IdentityNotFoundError(`policy '${input.policyId}' was not found`);
|
|
340
|
+
}
|
|
341
|
+
const permissionRows = await deps.repos.policyPermissions.listByPolicyId({
|
|
342
|
+
workspaceId: input.workspaceId,
|
|
343
|
+
policyId: input.policyId,
|
|
344
|
+
});
|
|
345
|
+
const conferredPermissions = permissionRows.map((row) => row.permission);
|
|
346
|
+
await assertGrantClamp({
|
|
347
|
+
deps,
|
|
348
|
+
workspaceId: input.workspaceId,
|
|
349
|
+
callerPrincipalId: input.callerPrincipalId,
|
|
350
|
+
conferredPermissions,
|
|
351
|
+
});
|
|
352
|
+
const attachment = {
|
|
353
|
+
id: deps.idGen.newId(),
|
|
354
|
+
workspaceId: input.workspaceId,
|
|
355
|
+
principalId: input.principalId,
|
|
356
|
+
policyId: input.policyId,
|
|
357
|
+
};
|
|
358
|
+
await deps.repos.principalPolicies.save(attachment);
|
|
359
|
+
return { attachment };
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=grant-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grant-service.js","sourceRoot":"","sources":["../../src/identity/grant-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,2BAA2B,EAAsB,MAAM,gBAAgB,CAAC;AAG5F,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,GAQxB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAoB;IACpD,OAAO;QACL,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;KAC3C,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,QAKlD;IACC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,GAAG,QAAQ,CAAC;IAEvE,IAAI,UAAU,GAAG,UAAU,CAAC;IAC5B,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;YAC7B,IAAI,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC;YACnC,WAAW,EAAE,iBAAiB;YAC9B,UAAU;YACV,OAAO,EAAE,EAAE,WAAW,EAAE;SACzB,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO;QAC3B,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED,MAAM,IAAI,sBAAsB,CAC9B,cAAc,iBAAiB,mCAAmC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAC3F,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EACrB,UAAU,CACX,CAAC;AACJ,CAAC;AAED;;sDAEsD;AACtD,SAAS,kBAAkB,CAAC,aAAgD,EAAE,UAAkB;IAC9F,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CACpC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,KAAK,GAAG,IAAI,GAAG,CAAC,YAAY,IAAI,IAAI,IAAI,GAAG,CAAC,cAAc,IAAI,IAAI,CAC1F,CAAC;IACF,IAAI,WAAW;QAAE,OAAO,IAAI,CAAC;IAC7B,OAAO,aAAa,CAAC,IAAI,CACvB,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,KAAK,UAAU,IAAI,GAAG,CAAC,YAAY,IAAI,IAAI,IAAI,GAAG,CAAC,cAAc,IAAI,IAAI,CACjG,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAKtC;IACC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,GAAG,QAAQ,CAAC;IAChF,MAAM,mBAAmB,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC/D,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAE7C,MAAM,aAAa,GAAG,MAAM,2BAA2B,CAAC;QACtD,IAAI,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC;QACnC,WAAW,EAAE,iBAAiB;QAC9B,WAAW;KACZ,CAAC,CAAC;IAEH,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,MAAM,CACrD,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,aAAa,EAAE,UAAU,CAAC,CAC/D,CAAC;IACF,IAAI,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,uBAAuB,CAC/B,cAAc,iBAAiB,gEAAgE,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAChI,oBAAoB,CACrB,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,2BAA2B,CAAC,QAK1C;IACC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;IACtF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,qBAAqB,CAAC,cAAc,WAAW,iBAAiB,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,uBAAuB,CAC/B,GAAG,cAAc,8DAA8D,MAAM,CAAC,IAAI,GAAG,CAC9F,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAGhC;IACC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;IAEjC,MAAM,4BAA4B,CAAC;QACjC,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,WAAW,EAAE,CAAC,aAAa,EAAE,eAAe,CAAC;KAC9C,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,IAAI,uBAAuB,CAAC,oCAAoC,CAAC,CAAC;IAC1E,CAAC;IACD,4FAA4F;IAC5F,yEAAyE;IACzE,MAAM,aAAa,GAAG,sBAAsB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7D,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,IAAI,uBAAuB,CAAC,aAAa,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzG,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,IAAI,qBAAqB,CAAC,aAAa,QAAQ,qBAAqB,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAEvC,MAAM,SAAS,GAAoB;QACjC,EAAE,EAAE,WAAW;QACf,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,QAAQ;QACrB,MAAM,EAAE,QAAQ;QAChB,SAAS,EAAE,MAAM;KAClB,CAAC;IACF,MAAM,IAAI,GAAe;QACvB,WAAW;QACX,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ;QACR,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,YAAY;KACb,CAAC;IAEF,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAElC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAGhC;IACC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;IAEjC,MAAM,4BAA4B,CAAC;QACjC,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,WAAW,EAAE,CAAC,aAAa,CAAC;KAC7B,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,uBAAuB,CAAC,uBAAuB,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,IAAI,GAAe;QACvB,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;QACtB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,IAAI;QACJ,SAAS,EAAE,KAAK;KACjB,CAAC;IACF,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAGlC;IACC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;IAEjC,MAAM,4BAA4B,CAAC;QACjC,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,WAAW,EAAE,CAAC,aAAa,CAAC;KAC7B,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,uBAAuB,CAAC,yBAAyB,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,MAAM,GAAiB;QAC3B,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;QACtB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK;QAChB,QAAQ,EAAE,KAAK;KAChB,CAAC;IACF,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAGhC;IACC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;IAEjC,MAAM,4BAA4B,CAAC;QACjC,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,WAAW,EAAE,CAAC,aAAa,CAAC;KAC7B,CAAC,CAAC;IAEH,MAAM,2BAA2B,CAAC;QAChC,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,cAAc,EAAE,aAAa;KAC9B,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACnG,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,qBAAqB,CAAC,SAAS,KAAK,CAAC,MAAM,iBAAiB,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC;QACjE,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;IACH,MAAM,sBAAsB,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9C,eAAe,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC3B,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CACzG,CACF,CAAC;IACF,MAAM,oBAAoB,GAAG,sBAAsB,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAExF,MAAM,gBAAgB,CAAC;QACrB,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,oBAAoB;KACrB,CAAC,CAAC;IAEH,MAAM,UAAU,GAAwB;QACtC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;QACtB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC;IACF,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjD,OAAO,EAAE,UAAU,EAAE,CAAC;AACxB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAGlC;IACC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;IAEjC,MAAM,4BAA4B,CAAC;QACjC,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,WAAW,EAAE,CAAC,aAAa,CAAC;KAC7B,CAAC,CAAC;IAEH,MAAM,2BAA2B,CAAC;QAChC,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,cAAc,EAAE,eAAe;KAChC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC1G,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,qBAAqB,CAAC,WAAW,KAAK,CAAC,QAAQ,iBAAiB,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,cAAc,CAAC;QACvE,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC;IACH,MAAM,oBAAoB,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAEzE,MAAM,gBAAgB,CAAC;QACrB,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,oBAAoB;KACrB,CAAC,CAAC;IAEH,MAAM,UAAU,GAA0B;QACxC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;QACtB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC;IACF,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACpD,OAAO,EAAE,UAAU,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PasswordHasherPort } from "./ports.js";
|
|
2
|
+
/**
|
|
3
|
+
* @file argon2id password hashing (INV-05).
|
|
4
|
+
*
|
|
5
|
+
* Purpose:
|
|
6
|
+
* The one real `PasswordHasherPort` adapter this pass — native argon2
|
|
7
|
+
* bindings, verified installable/buildable in this environment (see the
|
|
8
|
+
* Programmer handoff). Raw passwords are never stored or logged; only the
|
|
9
|
+
* hash produced here is persisted (`users.passwordHash`).
|
|
10
|
+
*
|
|
11
|
+
* Architectural role:
|
|
12
|
+
* Rule-of-two candidate per feature.spec's Dependencies table — only one
|
|
13
|
+
* adapter exists this pass, matching the spec's own "candidate" framing.
|
|
14
|
+
*/
|
|
15
|
+
/** Tunable cost parameters, defaulted to OWASP's current argon2id minimums. */
|
|
16
|
+
export interface Argon2PasswordHasherOptions {
|
|
17
|
+
/** KiB. OWASP minimum recommendation is 19456 (~19 MiB). */
|
|
18
|
+
memoryCost?: number;
|
|
19
|
+
/** Iteration count. OWASP minimum recommendation is 2 at this memory cost. */
|
|
20
|
+
timeCost?: number;
|
|
21
|
+
/** Degree of parallelism. */
|
|
22
|
+
parallelism?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* argon2id-backed `PasswordHasherPort`. `verify` never throws on a malformed
|
|
26
|
+
* or foreign hash — it resolves `false`, so a corrupted `passwordHash` row
|
|
27
|
+
* degrades to "wrong password," never to a 500 or an authentication bypass.
|
|
28
|
+
*
|
|
29
|
+
* @complexity O(1) calls into the native binding; cost is tuned by
|
|
30
|
+
* `memoryCost`/`timeCost`/`parallelism`, not by input size.
|
|
31
|
+
* @overallScore 100
|
|
32
|
+
*/
|
|
33
|
+
export declare class Argon2PasswordHasher implements PasswordHasherPort {
|
|
34
|
+
private readonly options;
|
|
35
|
+
constructor(options?: Argon2PasswordHasherOptions);
|
|
36
|
+
hash(password: string): Promise<string>;
|
|
37
|
+
verify(hash: string, password: string): Promise<boolean>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=hasher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hasher.d.ts","sourceRoot":"","sources":["../../src/identity/hasher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;;;;;;;;GAYG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,2BAA2B;IAC1C,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAQD;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,YAAW,kBAAkB;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwC;gBAEpD,OAAO,GAAE,2BAAgC;IAI/C,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASvC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAQ/D"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as argon2 from "argon2";
|
|
2
|
+
const DEFAULT_OPTIONS = {
|
|
3
|
+
memoryCost: 19456,
|
|
4
|
+
timeCost: 2,
|
|
5
|
+
parallelism: 1,
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* argon2id-backed `PasswordHasherPort`. `verify` never throws on a malformed
|
|
9
|
+
* or foreign hash — it resolves `false`, so a corrupted `passwordHash` row
|
|
10
|
+
* degrades to "wrong password," never to a 500 or an authentication bypass.
|
|
11
|
+
*
|
|
12
|
+
* @complexity O(1) calls into the native binding; cost is tuned by
|
|
13
|
+
* `memoryCost`/`timeCost`/`parallelism`, not by input size.
|
|
14
|
+
* @overallScore 100
|
|
15
|
+
*/
|
|
16
|
+
export class Argon2PasswordHasher {
|
|
17
|
+
options;
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
20
|
+
}
|
|
21
|
+
async hash(password) {
|
|
22
|
+
return argon2.hash(password, {
|
|
23
|
+
type: argon2.argon2id,
|
|
24
|
+
memoryCost: this.options.memoryCost,
|
|
25
|
+
timeCost: this.options.timeCost,
|
|
26
|
+
parallelism: this.options.parallelism,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async verify(hash, password) {
|
|
30
|
+
try {
|
|
31
|
+
return await argon2.verify(hash, password);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Malformed/foreign hash (e.g. a hand-edited row) — fail closed, not 500.
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=hasher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hasher.js","sourceRoot":"","sources":["../../src/identity/hasher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AA4BjC,MAAM,eAAe,GAA0C;IAC7D,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE,CAAC;IACX,WAAW,EAAE,CAAC;CACf,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,OAAO,oBAAoB;IACd,OAAO,CAAwC;IAEhE,YAAY,UAAuC,EAAE;QACnD,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,EAAE,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAgB;QACzB,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE;YAC3B,IAAI,EAAE,MAAM,CAAC,QAAQ;YACrB,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;YACnC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAC/B,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW;SACtC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,QAAgB;QACzC,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;YAC1E,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Public surface (barrel) for the `identity` library.
|
|
3
|
+
*
|
|
4
|
+
* A module's public contract is its `index.ts` — deep imports
|
|
5
|
+
* from outside this directory should go through here.
|
|
6
|
+
*/
|
|
7
|
+
export type { PrincipalKind, PrincipalStatus, PrincipalRecord, UserRecord, SessionRecord, RoleRecord, PolicyRecord, PolicyPermissionRecord, RolePolicyRecord, PrincipalRoleRecord, PrincipalPolicyRecord, } from "./types.js";
|
|
8
|
+
export { IdentityValidationError, IdentityNotFoundError, IdentityConflictError, AuthInvalidCredentialsError, IdentityForbiddenError, GrantExceedsIssuerError, OwnerRequiredError, PermissionUnknownError, } from "./types.js";
|
|
9
|
+
export type { PrincipalRepoPort, UserRepoPort, SessionRepoPort, RoleRepoPort, PolicyRepoPort, PolicyPermissionRepoPort, RolePolicyRepoPort, PrincipalRoleRepoPort, PrincipalPolicyRepoPort, IdentityRepos, PasswordHasherPort, } from "./ports.js";
|
|
10
|
+
export { InMemoryPrincipalRepo, InMemoryUserRepo, InMemorySessionRepo, InMemoryRoleRepo, InMemoryPolicyRepo, InMemoryPolicyPermissionRepo, InMemoryRolePolicyRepo, InMemoryPrincipalRoleRepo, InMemoryPrincipalPolicyRepo, } from "./repo.memory.js";
|
|
11
|
+
/**
|
|
12
|
+
* No concrete `PasswordHasherPort` implementation is exported here, deliberately. The reference
|
|
13
|
+
* adapter is argon2id, a native module: shipping it from this entry point would make a compiled
|
|
14
|
+
* binary a hard requirement of importing the identity domain — including for a host that only
|
|
15
|
+
* wants the types, the authorization rules, or the in-memory repositories. Hosts construct their
|
|
16
|
+
* own hasher and pass it as `deps.hasher`; the port is the contract, not the algorithm. A shared
|
|
17
|
+
* argon2 adapter belongs in `../server` once that layer exists.
|
|
18
|
+
*/
|
|
19
|
+
export { authorize, resolveEffectivePermissions, type AuthorizeContext, type AuthorizeResult, type AuthorizeDeps, } from "./authorize.js";
|
|
20
|
+
export { login, logout, validateSession, getEffectivePermissions, SESSION_TTL_MS, type AuthServiceDeps, } from "./auth-service.js";
|
|
21
|
+
export { seedIdentity, type SeedIdentityDeps, type SeedIdentityInput, type SeedIdentityResult } from "./seed.js";
|
|
22
|
+
export { createUser, createRole, createPolicy, assignRole, attachPolicy,
|
|
23
|
+
/** Exported so the assistant's read-only identity tools gate on the SAME caller-permission
|
|
24
|
+
* helper the mutating transitions use, rather than re-implementing the OR gate. */
|
|
25
|
+
assertCallerHasAnyPermission, } from "./grant-service.js";
|
|
26
|
+
/** The agent-tool surface for this domain (see `agent-tools.ts` for what is deliberately omitted). */
|
|
27
|
+
export { identityAgentToolCatalog, type AgentToolDefinition as IdentityAgentToolDefinition, type AgentToolSideEffect as IdentityAgentToolSideEffect, } from "./agent-tools.js";
|
|
28
|
+
export { parseIdentityToolInput, type IdentityToolInputResult } from "./agent-tool-input.js";
|
|
29
|
+
/** The users/roles/policies admin CRUD-completion amendment. */
|
|
30
|
+
export { disablePrincipal, enablePrincipal, updateUser, resetUserPassword, updateRole, updatePolicy, deleteRole, deletePolicy, writePolicyPermission,
|
|
31
|
+
/** OQ-10 — the inverse of `writePolicyPermission`; without it a policy's permission set was
|
|
32
|
+
* append-only (shrinking it meant `deletePolicy` + recreate, which INV-09 blocks once the
|
|
33
|
+
* policy is referenced). */
|
|
34
|
+
removePolicyPermission, } from "./admin-crud-service.js";
|
|
35
|
+
/**
|
|
36
|
+
* There is no wiring/composition export here, deliberately. Assembling concrete repositories into
|
|
37
|
+
* a dependency bag names a specific database handle, which would put one host's persistence choice
|
|
38
|
+
* on this library's public contract and drag that host's schema into every consumer's dependency
|
|
39
|
+
* closure. Hosts compose their own; this entry point exports the ports they compose against.
|
|
40
|
+
*/
|
|
41
|
+
export { normalizeUsername } from "./username.js";
|
|
42
|
+
export { registerPermission, listPermissions, isKnownPermission, permissionCatalog, type PermissionDescriptor, } from "./permissions.js";
|
|
43
|
+
/**
|
|
44
|
+
* The shared deprecate-old/grant-new permission migration
|
|
45
|
+
* mechanism (see `docs/decisions/permission-catalog-migration.md`). Sibling
|
|
46
|
+
* remediation efforts (Members/Analytics/Integrations)
|
|
47
|
+
* register their own `{from, to}` pair via `registerPermissionMigration`
|
|
48
|
+
* rather than hand-rolling a divergent copy.
|
|
49
|
+
*/
|
|
50
|
+
export { registerPermissionMigration, listPermissionMigrations, migrateDeprecatedPermissionGrants, type PermissionMigration, type MigrateDeprecatedPermissionGrantsDeps, type MigrateDeprecatedPermissionGrantsResult, } from "./permission-migrations.js";
|
|
51
|
+
/**
|
|
52
|
+
* The agent-tool wiring for this domain.
|
|
53
|
+
*
|
|
54
|
+
* `IdentityToolDeps` is declared structurally rather than derived from any host's request-scoped
|
|
55
|
+
* dependency bag, which is what lets a host satisfy it by passing whatever object it already has —
|
|
56
|
+
* the shape is the contract, so no host type needs to be named here.
|
|
57
|
+
*/
|
|
58
|
+
export { buildIdentityRegistrations, identityDerivedRisk, type IdentityToolDeps, } from "./tool-registrations.js";
|
|
59
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,YAAY,EACV,aAAa,EACb,eAAe,EACf,eAAe,EACf,UAAU,EACV,aAAa,EACb,UAAU,EACV,YAAY,EACZ,sBAAsB,EACtB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,cAAc,EACd,wBAAwB,EACxB,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EACvB,aAAa,EACb,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,4BAA4B,EAC5B,sBAAsB,EACtB,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;GAOG;AAEH,OAAO,EACL,SAAS,EACT,2BAA2B,EAC3B,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,KAAK,EACL,MAAM,EACN,eAAe,EACf,uBAAuB,EACvB,cAAc,EACd,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEjH,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,UAAU,EACV,YAAY;AACZ;mFACmF;AACnF,4BAA4B,GAC7B,MAAM,oBAAoB,CAAC;AAE5B,sGAAsG;AACtG,OAAO,EACL,wBAAwB,EACxB,KAAK,mBAAmB,IAAI,2BAA2B,EACvD,KAAK,mBAAmB,IAAI,2BAA2B,GACxD,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,KAAK,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAE7F,gEAAgE;AAChE,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,qBAAqB;AACrB;;6BAE6B;AAC7B,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAE1B;;;;;;GAMG;AACH,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,iCAAiC,EACjC,KAAK,mBAAmB,EACxB,KAAK,qCAAqC,EAC1C,KAAK,uCAAuC,GAC7C,MAAM,4BAA4B,CAAC;AAEpC;;;;;;GAMG;AACH,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export { IdentityValidationError, IdentityNotFoundError, IdentityConflictError, AuthInvalidCredentialsError, IdentityForbiddenError, GrantExceedsIssuerError, OwnerRequiredError, PermissionUnknownError, } from "./types.js";
|
|
2
|
+
export { InMemoryPrincipalRepo, InMemoryUserRepo, InMemorySessionRepo, InMemoryRoleRepo, InMemoryPolicyRepo, InMemoryPolicyPermissionRepo, InMemoryRolePolicyRepo, InMemoryPrincipalRoleRepo, InMemoryPrincipalPolicyRepo, } from "./repo.memory.js";
|
|
3
|
+
/**
|
|
4
|
+
* No concrete `PasswordHasherPort` implementation is exported here, deliberately. The reference
|
|
5
|
+
* adapter is argon2id, a native module: shipping it from this entry point would make a compiled
|
|
6
|
+
* binary a hard requirement of importing the identity domain — including for a host that only
|
|
7
|
+
* wants the types, the authorization rules, or the in-memory repositories. Hosts construct their
|
|
8
|
+
* own hasher and pass it as `deps.hasher`; the port is the contract, not the algorithm. A shared
|
|
9
|
+
* argon2 adapter belongs in `../server` once that layer exists.
|
|
10
|
+
*/
|
|
11
|
+
export { authorize, resolveEffectivePermissions, } from "./authorize.js";
|
|
12
|
+
export { login, logout, validateSession, getEffectivePermissions, SESSION_TTL_MS, } from "./auth-service.js";
|
|
13
|
+
export { seedIdentity } from "./seed.js";
|
|
14
|
+
export { createUser, createRole, createPolicy, assignRole, attachPolicy,
|
|
15
|
+
/** Exported so the assistant's read-only identity tools gate on the SAME caller-permission
|
|
16
|
+
* helper the mutating transitions use, rather than re-implementing the OR gate. */
|
|
17
|
+
assertCallerHasAnyPermission, } from "./grant-service.js";
|
|
18
|
+
/** The agent-tool surface for this domain (see `agent-tools.ts` for what is deliberately omitted). */
|
|
19
|
+
export { identityAgentToolCatalog, } from "./agent-tools.js";
|
|
20
|
+
export { parseIdentityToolInput } from "./agent-tool-input.js";
|
|
21
|
+
/** The users/roles/policies admin CRUD-completion amendment. */
|
|
22
|
+
export { disablePrincipal, enablePrincipal, updateUser, resetUserPassword, updateRole, updatePolicy, deleteRole, deletePolicy, writePolicyPermission,
|
|
23
|
+
/** OQ-10 — the inverse of `writePolicyPermission`; without it a policy's permission set was
|
|
24
|
+
* append-only (shrinking it meant `deletePolicy` + recreate, which INV-09 blocks once the
|
|
25
|
+
* policy is referenced). */
|
|
26
|
+
removePolicyPermission, } from "./admin-crud-service.js";
|
|
27
|
+
/**
|
|
28
|
+
* There is no wiring/composition export here, deliberately. Assembling concrete repositories into
|
|
29
|
+
* a dependency bag names a specific database handle, which would put one host's persistence choice
|
|
30
|
+
* on this library's public contract and drag that host's schema into every consumer's dependency
|
|
31
|
+
* closure. Hosts compose their own; this entry point exports the ports they compose against.
|
|
32
|
+
*/
|
|
33
|
+
export { normalizeUsername } from "./username.js";
|
|
34
|
+
export { registerPermission, listPermissions, isKnownPermission, permissionCatalog, } from "./permissions.js";
|
|
35
|
+
/**
|
|
36
|
+
* The shared deprecate-old/grant-new permission migration
|
|
37
|
+
* mechanism (see `docs/decisions/permission-catalog-migration.md`). Sibling
|
|
38
|
+
* remediation efforts (Members/Analytics/Integrations)
|
|
39
|
+
* register their own `{from, to}` pair via `registerPermissionMigration`
|
|
40
|
+
* rather than hand-rolling a divergent copy.
|
|
41
|
+
*/
|
|
42
|
+
export { registerPermissionMigration, listPermissionMigrations, migrateDeprecatedPermissionGrants, } from "./permission-migrations.js";
|
|
43
|
+
/**
|
|
44
|
+
* The agent-tool wiring for this domain.
|
|
45
|
+
*
|
|
46
|
+
* `IdentityToolDeps` is declared structurally rather than derived from any host's request-scoped
|
|
47
|
+
* dependency bag, which is what lets a host satisfy it by passing whatever object it already has —
|
|
48
|
+
* the shape is the contract, so no host type needs to be named here.
|
|
49
|
+
*/
|
|
50
|
+
export { buildIdentityRegistrations, identityDerivedRisk, } from "./tool-registrations.js";
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAoBA,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAgBpB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,4BAA4B,EAC5B,sBAAsB,EACtB,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;GAOG;AAEH,OAAO,EACL,SAAS,EACT,2BAA2B,GAI5B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,KAAK,EACL,MAAM,EACN,eAAe,EACf,uBAAuB,EACvB,cAAc,GAEf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,YAAY,EAA0E,MAAM,WAAW,CAAC;AAEjH,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,UAAU,EACV,YAAY;AACZ;mFACmF;AACnF,4BAA4B,GAC7B,MAAM,oBAAoB,CAAC;AAE5B,sGAAsG;AACtG,OAAO,EACL,wBAAwB,GAGzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAgC,MAAM,uBAAuB,CAAC;AAE7F,gEAAgE;AAChE,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,qBAAqB;AACrB;;6BAE6B;AAC7B,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,GAElB,MAAM,kBAAkB,CAAC;AAE1B;;;;;;GAMG;AACH,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,iCAAiC,GAIlC,MAAM,4BAA4B,CAAC;AAEpC;;;;;;GAMG;AACH,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,GAEpB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Password policy (NIST SP 800-63B aligned): a length floor only, no composition rules.
|
|
3
|
+
*
|
|
4
|
+
* NIST SP 800-63B — the current published memorized-secret guidance — recommends a minimum
|
|
5
|
+
* length requirement and explicitly recommends AGAINST composition rules (mandatory uppercase,
|
|
6
|
+
* digit, or symbol). Composition rules measurably push people toward predictable, guessable
|
|
7
|
+
* patterns ("Password1!") rather than genuinely stronger secrets, which is why this module
|
|
8
|
+
* enforces length only.
|
|
9
|
+
*
|
|
10
|
+
* `createUser` (`grant-service.ts`) and `resetUserPassword` (`admin-crud-service.ts`) are the
|
|
11
|
+
* identity system's only two write paths that ever set a password, confirmed by tracing the
|
|
12
|
+
* whole call graph — both call this module.
|
|
13
|
+
*
|
|
14
|
+
* Two things this deliberately does NOT do, both load-bearing:
|
|
15
|
+
* - Never reaches `seed.ts`'s first-boot owner password. `seedIdentity` hashes it directly
|
|
16
|
+
* (`deps.hasher.hash(ownerPassword)`, `seed.ts:317`) and calls neither `createUser` nor
|
|
17
|
+
* `resetUserPassword` — confirmed before writing this module. That separation is intentional
|
|
18
|
+
* to preserve here: the host chooses the first-boot owner password (`SeedIdentityInput` requires
|
|
19
|
+
* it and supplies no default), and an existing installation is already authenticating with
|
|
20
|
+
* whatever it chose. Enforcing this policy on that path would lock out every such installation
|
|
21
|
+
* whose chosen value predates the policy.
|
|
22
|
+
* - Never re-validates at login. This is a write-time policy — `login`/`verify` never call it.
|
|
23
|
+
* An account whose password predates this policy (or was seeded) must keep authenticating; NIST
|
|
24
|
+
* 800-63B's own guidance is that length rules apply when a secret is *chosen*, not retroactively
|
|
25
|
+
* to secrets already in use.
|
|
26
|
+
*/
|
|
27
|
+
/** NIST SP 800-63B's recommended floor. */
|
|
28
|
+
export declare const MIN_PASSWORD_LENGTH = 12;
|
|
29
|
+
/**
|
|
30
|
+
* Generous upper bound — not itself a security requirement (argon2id's cost is tuned by its
|
|
31
|
+
* `memoryCost`/`timeCost`/`parallelism` parameters, not by input size — see `hasher.ts`'s own
|
|
32
|
+
* `@complexity` note), but a defense-in-depth cap on how large a string this service will accept
|
|
33
|
+
* and pass to the hasher at all, independent of whatever limit (if any) sits in front of it at
|
|
34
|
+
* the HTTP layer. Comfortably above any realistic human-typed passphrase.
|
|
35
|
+
*/
|
|
36
|
+
export declare const MAX_PASSWORD_LENGTH = 512;
|
|
37
|
+
/**
|
|
38
|
+
* Validates `password` against the length-only policy.
|
|
39
|
+
*
|
|
40
|
+
* Measures length in Unicode CODE POINTS (`[...password].length`), not UTF-16 code units
|
|
41
|
+
* (`password.length`): a passphrase built from astral-plane characters (many emoji, some
|
|
42
|
+
* CJK/historic scripts) is represented as a surrogate pair per character in a JS string, so plain
|
|
43
|
+
* `.length` overcounts those characters relative to what a human typing them perceives as "12
|
|
44
|
+
* characters" — silently misjudging the exact floor this function states. No trimming, no
|
|
45
|
+
* character allowlist: every printable character, including leading/trailing spaces and full
|
|
46
|
+
* Unicode, is accepted as typed. Silently altering the input (trimming, stripping) would make the
|
|
47
|
+
* stored credential differ from the secret the operator actually chose.
|
|
48
|
+
*
|
|
49
|
+
* @returns `null` if `password` satisfies the policy, otherwise an operator-facing message
|
|
50
|
+
* stating the requirement plainly — used verbatim as the thrown `IdentityValidationError`'s
|
|
51
|
+
* message by both call sites, and rendered as-is through the admin's `describeApiError` layer.
|
|
52
|
+
*
|
|
53
|
+
* @complexity O(n) in the password's length — spreading a string into code points is a single
|
|
54
|
+
* linear pass, which is the minimum work a correct (non-UTF-16-code-unit) count requires.
|
|
55
|
+
* @overallScore 100
|
|
56
|
+
*/
|
|
57
|
+
export declare function validatePasswordPolicy(password: string): string | null;
|
|
58
|
+
//# sourceMappingURL=password-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-policy.d.ts","sourceRoot":"","sources":["../../src/identity/password-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAStE"}
|