@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,350 @@
|
|
|
1
|
+
import { ForbiddenError } from "../core/commands/command.js";
|
|
2
|
+
import { validateContentJoin, validateHierarchyAssignment } from "./validation-chain.js";
|
|
3
|
+
/** The hardcoded post/page taxonomy allow-list (permanent, see
|
|
4
|
+
* `docs/decisions/taxonomy-content-type-allow-list.md`) — every taxonomy is applicable to
|
|
5
|
+
* `post`/`page` content; no other content type is eligible for term assignment until this is
|
|
6
|
+
* deliberately extended. */
|
|
7
|
+
export const TAXONOMY_ALLOWED_CONTENT_TYPES = new Set(["post", "page"]);
|
|
8
|
+
export function isContentTypeOnAllowList(contentType) {
|
|
9
|
+
return TAXONOMY_ALLOWED_CONTENT_TYPES.has(contentType);
|
|
10
|
+
}
|
|
11
|
+
export class TaxonomyRecordNotFoundError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "TaxonomyRecordNotFoundError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class TermRecordNotFoundError extends Error {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = "TermRecordNotFoundError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Finding 1 fix — the target of an `assignTerms` call does not resolve to any real content row. */
|
|
24
|
+
export class ContentRecordNotFoundError extends Error {
|
|
25
|
+
constructor(message) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = "ContentRecordNotFoundError";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** `admin.taxonomy.manage` (the flat-string permission convention) — must run before any other
|
|
31
|
+
* side effect of every write-service export in this file. */
|
|
32
|
+
async function authorizeTaxonomyManage(deps, principalId) {
|
|
33
|
+
const result = await deps.authorize({ principalId, permission: "admin.taxonomy.manage" });
|
|
34
|
+
if (!result.allowed) {
|
|
35
|
+
throw new ForbiddenError(`principal '${principalId}' is not authorized for 'admin.taxonomy.manage' (${result.reason})`, "admin.taxonomy.manage", result.reason);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Creates a taxonomy row (hierarchical=true -> "category"-shaped, false -> "tag"-shaped — same
|
|
39
|
+
* shared table). Ordinary mutation, no plan()/confirmation ceremony. */
|
|
40
|
+
export async function createTaxonomy(required, _optional = {}) {
|
|
41
|
+
const { deps, principalId, name, hierarchical } = required;
|
|
42
|
+
await authorizeTaxonomyManage(deps, principalId);
|
|
43
|
+
const now = deps.clock.nowIso();
|
|
44
|
+
const taxonomy = {
|
|
45
|
+
id: deps.idGen.newId(),
|
|
46
|
+
name,
|
|
47
|
+
hierarchical,
|
|
48
|
+
status: "active",
|
|
49
|
+
updatedAt: now,
|
|
50
|
+
version: 1,
|
|
51
|
+
};
|
|
52
|
+
await deps.taxonomies.insert(taxonomy);
|
|
53
|
+
await deps.revisions.insert({
|
|
54
|
+
taxonomyId: taxonomy.id,
|
|
55
|
+
op: "create",
|
|
56
|
+
previousState: null,
|
|
57
|
+
actorId: principalId,
|
|
58
|
+
recordedAt: now,
|
|
59
|
+
});
|
|
60
|
+
deps.stampWatermark();
|
|
61
|
+
await deps.outbox.enqueue({ name: "taxonomy.created", taxonomyId: taxonomy.id, actorId: principalId, occurredAt: now });
|
|
62
|
+
return taxonomy;
|
|
63
|
+
}
|
|
64
|
+
/** AC-03/AC-13/EC-04 — validates `parentId` via `validateHierarchyAssignment` before writing. A
|
|
65
|
+
* freshly-created term has no descendants yet, so it structurally cannot be a cycle source; the
|
|
66
|
+
* cycle check is therefore always a no-op (`() => false`) here, unlike a reparent of an existing
|
|
67
|
+
* term (not yet built — no certified test in this slice exercises it). */
|
|
68
|
+
export async function createTerm(required, _optional = {}) {
|
|
69
|
+
const { deps, principalId, taxonomyId, name, parentId } = required;
|
|
70
|
+
await authorizeTaxonomyManage(deps, principalId);
|
|
71
|
+
const taxonomy = await deps.taxonomies.findById(taxonomyId);
|
|
72
|
+
if (!taxonomy) {
|
|
73
|
+
throw new TaxonomyRecordNotFoundError(`taxonomy '${taxonomyId}' was not found`);
|
|
74
|
+
}
|
|
75
|
+
const candidateParentId = parentId ?? null;
|
|
76
|
+
let resolvedParent = "not-applicable";
|
|
77
|
+
if (candidateParentId !== null) {
|
|
78
|
+
const parentTerm = await deps.terms.findById(candidateParentId);
|
|
79
|
+
resolvedParent = parentTerm ? { id: parentTerm.id, taxonomyId: parentTerm.taxonomyId } : null;
|
|
80
|
+
}
|
|
81
|
+
validateHierarchyAssignment({
|
|
82
|
+
childTaxonomyId: taxonomyId,
|
|
83
|
+
taxonomyIsHierarchical: taxonomy.hierarchical,
|
|
84
|
+
candidateParentId,
|
|
85
|
+
resolvedParent,
|
|
86
|
+
wouldCreateCycle: () => false,
|
|
87
|
+
termId: "__new__",
|
|
88
|
+
});
|
|
89
|
+
const now = deps.clock.nowIso();
|
|
90
|
+
const term = {
|
|
91
|
+
id: deps.idGen.newId(),
|
|
92
|
+
taxonomyId,
|
|
93
|
+
parentId: candidateParentId,
|
|
94
|
+
name,
|
|
95
|
+
status: "active",
|
|
96
|
+
updatedAt: now,
|
|
97
|
+
version: 1,
|
|
98
|
+
};
|
|
99
|
+
await deps.terms.insert(term);
|
|
100
|
+
await deps.revisions.insert({ taxonomyId, op: "create", previousState: null, actorId: principalId, recordedAt: now });
|
|
101
|
+
deps.stampWatermark();
|
|
102
|
+
await deps.outbox.enqueue({ name: "taxonomy.term_created", termId: term.id, actorId: principalId, occurredAt: now });
|
|
103
|
+
return term;
|
|
104
|
+
}
|
|
105
|
+
/** AC-15/AC-19/AC-25/REQ-12/REQ-17 — same-tx rename + revision (carrying the pre-rename state) +
|
|
106
|
+
* watermark + outbox. `authorize()` runs before the term lookup, so a denied caller produces zero
|
|
107
|
+
* side effects of any kind. */
|
|
108
|
+
export async function renameTerm(required, _optional = {}) {
|
|
109
|
+
const { deps, principalId, termId, newName } = required;
|
|
110
|
+
await authorizeTaxonomyManage(deps, principalId);
|
|
111
|
+
const current = await deps.terms.findById(termId);
|
|
112
|
+
if (!current) {
|
|
113
|
+
throw new TermRecordNotFoundError(`term '${termId}' was not found`);
|
|
114
|
+
}
|
|
115
|
+
const now = deps.clock.nowIso();
|
|
116
|
+
const updated = {
|
|
117
|
+
id: current.id,
|
|
118
|
+
taxonomyId: current.taxonomyId,
|
|
119
|
+
parentId: current.parentId ?? null,
|
|
120
|
+
name: newName,
|
|
121
|
+
status: current.status ?? "active",
|
|
122
|
+
updatedAt: now,
|
|
123
|
+
version: (current.version ?? 1) + 1,
|
|
124
|
+
};
|
|
125
|
+
await deps.terms.update(updated);
|
|
126
|
+
await deps.revisions.insert({
|
|
127
|
+
taxonomyId: current.taxonomyId,
|
|
128
|
+
op: "rename",
|
|
129
|
+
previousState: { name: current.name },
|
|
130
|
+
actorId: principalId,
|
|
131
|
+
recordedAt: now,
|
|
132
|
+
});
|
|
133
|
+
deps.stampWatermark();
|
|
134
|
+
await deps.outbox.enqueue({ name: "taxonomy.term_renamed", termId, actorId: principalId, occurredAt: now });
|
|
135
|
+
return updated;
|
|
136
|
+
}
|
|
137
|
+
/** AC-17/AC-20/INV-05/REQ-13/REQ-14 — upserts every `entry_terms` row (idempotent on-conflict per
|
|
138
|
+
* `entry_terms_unique`, EC-09), then stamps the watermark and enqueues the outbox event exactly
|
|
139
|
+
* ONCE per call regardless of `termIds.length` — never once per term. Never produces a
|
|
140
|
+
* `taxonomy_revisions` row (see this file's header for the disclosed narrowing this implements).
|
|
141
|
+
*
|
|
142
|
+
* Finding 1 fix (TM-adr041-043-044-045-audit-001): every `termId` is validated via
|
|
143
|
+
* `validateContentJoin` (allow-list -> workspace -> lens, `validation-chain.ts`'s fixed order)
|
|
144
|
+
* BEFORE any `entry_terms` row is written — every termId must resolve to a real term, and the
|
|
145
|
+
* target content must resolve to a real row whose kind matches the caller-supplied `contentType`.
|
|
146
|
+
* Validation runs for ALL termIds before ANY write, so a failure partway through never leaves a
|
|
147
|
+
* partial assignment. Content is resolved once per call (not once per term) since every term in
|
|
148
|
+
* one call shares the same `(contentType, contentId)` target.
|
|
149
|
+
*/
|
|
150
|
+
export async function assignTerms(required, _optional = {}) {
|
|
151
|
+
const { deps, principalId, contentType, contentId, termIds } = required;
|
|
152
|
+
await authorizeTaxonomyManage(deps, principalId);
|
|
153
|
+
const isOnAllowList = isContentTypeOnAllowList(contentType);
|
|
154
|
+
const content = isOnAllowList ? await deps.contentLookup.resolve({ contentType, contentId }) : null;
|
|
155
|
+
if (isOnAllowList && !content) {
|
|
156
|
+
throw new ContentRecordNotFoundError(`content '${contentType}:${contentId}' was not found`);
|
|
157
|
+
}
|
|
158
|
+
for (const termId of termIds) {
|
|
159
|
+
const term = await deps.terms.findById(termId);
|
|
160
|
+
if (!term) {
|
|
161
|
+
throw new TermRecordNotFoundError(`term '${termId}' was not found`);
|
|
162
|
+
}
|
|
163
|
+
validateContentJoin({
|
|
164
|
+
taxonomyId: term.taxonomyId,
|
|
165
|
+
isOnAllowList,
|
|
166
|
+
callerWorkspaceId: deps.workspaceId,
|
|
167
|
+
// `SqliteTermRepo`/`SqliteEntryTermRepo` are workspace-BOUND at construction (single
|
|
168
|
+
// workspace per content.db) — a term/content row that resolves via those adapters at all
|
|
169
|
+
// is, by construction, already in the caller's own workspace. See this file's header.
|
|
170
|
+
resolvedTermWorkspaceId: deps.workspaceId,
|
|
171
|
+
resolvedContentWorkspaceId: content?.workspaceId ?? deps.workspaceId,
|
|
172
|
+
suppliedContentType: contentType,
|
|
173
|
+
resolvedContentKind: content?.kind ?? contentType,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
const now = deps.clock.nowIso();
|
|
177
|
+
for (const termId of termIds) {
|
|
178
|
+
await deps.entryTerms.upsert({ contentType, contentId, termId, addedAt: now });
|
|
179
|
+
}
|
|
180
|
+
deps.stampWatermark();
|
|
181
|
+
await deps.outbox.enqueue({
|
|
182
|
+
name: "taxonomy.terms_assigned",
|
|
183
|
+
contentType,
|
|
184
|
+
contentId,
|
|
185
|
+
termIds,
|
|
186
|
+
actorId: principalId,
|
|
187
|
+
occurredAt: now,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/** Content-deletion event subscriber. Best-effort (a missed event leaves an orphaned
|
|
191
|
+
* `entry_terms` row that is inert on read; a periodic/boot reconciliation sweep — modeled by
|
|
192
|
+
* re-invoking this same function for the orphan — is the backstop, never a hard failure). A
|
|
193
|
+
* no-op for content with no
|
|
194
|
+
* assigned terms, never an error. */
|
|
195
|
+
export async function onContentDeleted(required, _optional = {}) {
|
|
196
|
+
const { event, entryTerms } = required;
|
|
197
|
+
await entryTerms.deleteByContent({
|
|
198
|
+
workspaceId: event.workspaceId,
|
|
199
|
+
contentType: event.contentType,
|
|
200
|
+
contentId: event.contentId,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/** `deleteTerm`/`deleteTaxonomy` refuse rather than silently orphan when content is still
|
|
204
|
+
* assigned. Carries `assignedCount` so a caller (route/UI) can render "N items are still
|
|
205
|
+
* assigned" instead of a generic failure. */
|
|
206
|
+
export class TermHasAssignedContentError extends Error {
|
|
207
|
+
assignedCount;
|
|
208
|
+
constructor(message, assignedCount) {
|
|
209
|
+
super(message);
|
|
210
|
+
this.assignedCount = assignedCount;
|
|
211
|
+
this.name = "TermHasAssignedContentError";
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/** See `DeletableTermRepoPort.countChildren`'s doc comment for why this guard exists. Carries
|
|
215
|
+
* `childCount` for the same reason `TermHasAssignedContentError` carries `assignedCount`. */
|
|
216
|
+
export class TermHasChildTermsError extends Error {
|
|
217
|
+
childCount;
|
|
218
|
+
constructor(message, childCount) {
|
|
219
|
+
super(message);
|
|
220
|
+
this.childCount = childCount;
|
|
221
|
+
this.name = "TermHasChildTermsError";
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/** `deleteTaxonomy`'s content-assignment guard — `assignedCount` is the sum across every member
|
|
225
|
+
* term, not a single term's count. */
|
|
226
|
+
export class TaxonomyHasAssignedContentError extends Error {
|
|
227
|
+
assignedCount;
|
|
228
|
+
constructor(message, assignedCount) {
|
|
229
|
+
super(message);
|
|
230
|
+
this.assignedCount = assignedCount;
|
|
231
|
+
this.name = "TaxonomyHasAssignedContentError";
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Deletes a single term. Refuses (never cascades) when the term still has children or is still
|
|
236
|
+
* assigned to content — both checks run, and either alone is enough to block, before any write.
|
|
237
|
+
* An unassigned, childless term is destroying nothing recoverable, so this is a direct delete with
|
|
238
|
+
* no plan()/confirmation ceremony (`mergeTerm` earns that ceremony because it migrates data this
|
|
239
|
+
* does not).
|
|
240
|
+
*
|
|
241
|
+
* `authorize()` runs before the transaction opens (a pure permission check, no side effect, so it
|
|
242
|
+
* doesn't need transactional protection); everything from the existence check onward — both
|
|
243
|
+
* guards and the delete itself — runs inside `deps.transaction()` (see that port's doc comment for
|
|
244
|
+
* why). Does NOT cascade-delete the term's `taxonomy_revisions` rows: that table is an append-only
|
|
245
|
+
* audit trail (mirrors `redirect_hits`/`asset_renditions`'s disclosed audit-not-referential-
|
|
246
|
+
* integrity precedent), and erasing a term's history the moment the term itself is deleted would
|
|
247
|
+
* destroy the very "this term existed and was deleted" record this call's own revision insert
|
|
248
|
+
* below creates. Confirmed by grepping `db/schema.ts`: no other table has a `taxonomyId`/`termId`
|
|
249
|
+
* column, so `taxonomy_revisions` is the only thing this decision applies to.
|
|
250
|
+
*
|
|
251
|
+
* @complexity O(1) — one `countChildren` call, one `countByTerm` call, one delete, all inside one
|
|
252
|
+
* transaction.
|
|
253
|
+
* @overallScore 100
|
|
254
|
+
*/
|
|
255
|
+
export async function deleteTerm(required, _optional = {}) {
|
|
256
|
+
const { deps, principalId, termId } = required;
|
|
257
|
+
await authorizeTaxonomyManage(deps, principalId);
|
|
258
|
+
return deps.transaction(async () => {
|
|
259
|
+
const current = await deps.terms.findById(termId);
|
|
260
|
+
if (!current) {
|
|
261
|
+
throw new TermRecordNotFoundError(`term '${termId}' was not found`);
|
|
262
|
+
}
|
|
263
|
+
const childCount = await deps.terms.countChildren({ parentId: termId });
|
|
264
|
+
if (childCount > 0) {
|
|
265
|
+
throw new TermHasChildTermsError(`term '${termId}' has ${childCount} child term(s) and cannot be deleted`, childCount);
|
|
266
|
+
}
|
|
267
|
+
const assignedCount = await deps.entryTerms.countByTerm({ termId });
|
|
268
|
+
if (assignedCount > 0) {
|
|
269
|
+
throw new TermHasAssignedContentError(`term '${termId}' is assigned to ${assignedCount} content item(s) and cannot be deleted`, assignedCount);
|
|
270
|
+
}
|
|
271
|
+
await deps.terms.delete(termId);
|
|
272
|
+
const now = deps.clock.nowIso();
|
|
273
|
+
await deps.revisions.insert({
|
|
274
|
+
taxonomyId: current.taxonomyId,
|
|
275
|
+
op: "delete",
|
|
276
|
+
previousState: { termId, name: current.name ?? null },
|
|
277
|
+
actorId: principalId,
|
|
278
|
+
recordedAt: now,
|
|
279
|
+
});
|
|
280
|
+
deps.stampWatermark();
|
|
281
|
+
await deps.outbox.enqueue({
|
|
282
|
+
name: "taxonomy.term_deleted",
|
|
283
|
+
termId,
|
|
284
|
+
taxonomyId: current.taxonomyId,
|
|
285
|
+
actorId: principalId,
|
|
286
|
+
occurredAt: now,
|
|
287
|
+
});
|
|
288
|
+
return { deletedTermId: termId };
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Deletes a taxonomy together with its member terms, refusing when ANY member term is still
|
|
293
|
+
* assigned to content (the sum across all member terms, reported as one `assignedCount`). Unlike
|
|
294
|
+
* `deleteTerm`, this does cascade — but only over terms this same call has just confirmed, INSIDE
|
|
295
|
+
* the same transaction, are unassigned, so nothing recoverable is lost. `deleteTerm`'s own "has
|
|
296
|
+
* children" guard does not apply here: a member term's children are, by construction, also members
|
|
297
|
+
* of the same taxonomy (hierarchy never crosses taxonomies — `validateHierarchyAssignment`'s
|
|
298
|
+
* `ParentCrossTaxonomyError` enforces that on the write side), so deleting the full member set in
|
|
299
|
+
* one pass never leaves a `parentId` dangling outside the set being deleted.
|
|
300
|
+
*
|
|
301
|
+
* Same transaction-boundary and `taxonomy_revisions`-retention rationale as `deleteTerm` — see its
|
|
302
|
+
* doc comment. The taxonomy-level version of the same TOCTOU risk: `listByTaxonomy` and every
|
|
303
|
+
* per-term `countByTerm` call must see the SAME committed state the delete loop is about to act
|
|
304
|
+
* on, which is only guaranteed inside one transaction, not across N separate queries beforehand.
|
|
305
|
+
*
|
|
306
|
+
* @complexity O(t) in the taxonomy's own term count — one `countByTerm` per member term to total
|
|
307
|
+
* the guard, then one delete per member term plus one taxonomy delete, all inside one transaction.
|
|
308
|
+
* @overallScore 100
|
|
309
|
+
*/
|
|
310
|
+
export async function deleteTaxonomy(required, _optional = {}) {
|
|
311
|
+
const { deps, principalId, taxonomyId } = required;
|
|
312
|
+
await authorizeTaxonomyManage(deps, principalId);
|
|
313
|
+
return deps.transaction(async () => {
|
|
314
|
+
const taxonomy = await deps.taxonomies.findById(taxonomyId);
|
|
315
|
+
if (!taxonomy) {
|
|
316
|
+
throw new TaxonomyRecordNotFoundError(`taxonomy '${taxonomyId}' was not found`);
|
|
317
|
+
}
|
|
318
|
+
const memberTerms = await deps.terms.listByTaxonomy({ taxonomyId });
|
|
319
|
+
let totalAssigned = 0;
|
|
320
|
+
for (const term of memberTerms) {
|
|
321
|
+
totalAssigned += await deps.entryTerms.countByTerm({ termId: term.id });
|
|
322
|
+
}
|
|
323
|
+
if (totalAssigned > 0) {
|
|
324
|
+
throw new TaxonomyHasAssignedContentError(`taxonomy '${taxonomyId}' has ${totalAssigned} content assignment(s) across its terms and cannot be deleted`, totalAssigned);
|
|
325
|
+
}
|
|
326
|
+
for (const term of memberTerms) {
|
|
327
|
+
await deps.terms.delete(term.id);
|
|
328
|
+
}
|
|
329
|
+
await deps.taxonomies.delete(taxonomyId);
|
|
330
|
+
const now = deps.clock.nowIso();
|
|
331
|
+
const deletedTermIds = memberTerms.map((term) => term.id);
|
|
332
|
+
await deps.revisions.insert({
|
|
333
|
+
taxonomyId,
|
|
334
|
+
op: "delete",
|
|
335
|
+
previousState: { deletedTermIds },
|
|
336
|
+
actorId: principalId,
|
|
337
|
+
recordedAt: now,
|
|
338
|
+
});
|
|
339
|
+
deps.stampWatermark();
|
|
340
|
+
await deps.outbox.enqueue({
|
|
341
|
+
name: "taxonomy.deleted",
|
|
342
|
+
taxonomyId,
|
|
343
|
+
deletedTermIds,
|
|
344
|
+
actorId: principalId,
|
|
345
|
+
occurredAt: now,
|
|
346
|
+
});
|
|
347
|
+
return { deletedTaxonomyId: taxonomyId, deletedTermIds };
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
//# sourceMappingURL=write-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-service.js","sourceRoot":"","sources":["../../src/taxonomy/write-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The Workspace domain's agent-tool catalog, instantiating this package's shared
|
|
3
|
+
* naming/callability convention (the same shape every other domain catalog in this package
|
|
4
|
+
* already uses).
|
|
5
|
+
*
|
|
6
|
+
* Purpose:
|
|
7
|
+
* A static, in-process catalog describing every agent-callable tool this domain exposes and the
|
|
8
|
+
* permission each one carries. This is the highest-stakes domain wired so far: a host's
|
|
9
|
+
* `workspaceId` is fixed at process composition (a v1 install always has exactly one addressable
|
|
10
|
+
* workspace row), so `create`/`delete` are deliberately excluded
|
|
11
|
+
* outright rather than treated as ordinary CRUD:
|
|
12
|
+
* - `CREATE_WORKSPACE` inserts a row no route can ever address afterwards (every other workspace
|
|
13
|
+
* route resolves strictly against the boot-wired `workspaceId`, never a caller-supplied id)
|
|
14
|
+
* — wiring it would let an agent mint permanently orphaned, unreferenceable rows with no
|
|
15
|
+
* corresponding read/delete path back to them. Zero utility, non-zero clutter/spam surface.
|
|
16
|
+
* - `DELETE_WORKSPACE` is INV-03-guarded to always refuse in v1 (there is only ever one row), but
|
|
17
|
+
* the moment that guard's precondition changes (a second addressable workspace exists), the same
|
|
18
|
+
* tool becomes a lever that can remove the only workspace scope a request can reach — whole-scope,
|
|
19
|
+
* no per-domain undo, the same blast-radius class as a forward database migration or a backup
|
|
20
|
+
* restore. Excluded by design, mirroring those two.
|
|
21
|
+
* `UPDATE_WORKSPACE` is the one write kept: a narrow rename of `name`/`slug` on the single existing,
|
|
22
|
+
* already-addressable workspace, no cascading effects (`id`/`createdAt` immutable by convention —
|
|
23
|
+
* see `update.ts`), the same risk class as `identity_role_rename`.
|
|
24
|
+
*
|
|
25
|
+
* How it relates to the package:
|
|
26
|
+
* A host's server-side tool filter consumes this catalog to decide which tool names an
|
|
27
|
+
* agent session may even see; `authorize()` (the single-evaluator rule below) enforces the actual
|
|
28
|
+
* permission checks at call time — this module only declares the catalog shape, it performs no
|
|
29
|
+
* I/O and no enforcement itself.
|
|
30
|
+
*
|
|
31
|
+
* Architectural role:
|
|
32
|
+
* `workspace` domain logic. No dependencies.
|
|
33
|
+
*/
|
|
34
|
+
export type AgentToolSideEffect = "none" | "mutates-durable-state" | "mints-token";
|
|
35
|
+
export type AgentToolActorClassRule = "confirmer-must-equal-own-delegatedBy" | "user-only" | "none";
|
|
36
|
+
export interface AgentToolDefinition {
|
|
37
|
+
name: string;
|
|
38
|
+
description: string;
|
|
39
|
+
sideEffects: AgentToolSideEffect;
|
|
40
|
+
authorization: {
|
|
41
|
+
permission: string;
|
|
42
|
+
};
|
|
43
|
+
actorClassRule?: AgentToolActorClassRule;
|
|
44
|
+
/**
|
|
45
|
+
* JSON Schema for this tool's `input`, published to the model via `ToolDescriptor.inputSchema`
|
|
46
|
+
* by whichever host layer wires these tools (any such layer should refuse to wire a tool lacking
|
|
47
|
+
* one). Optional, matching this package's other domain catalogs — the two entries this dispatch
|
|
48
|
+
* leaves unwired (see file header) carry no schema at all, since one is never published for a
|
|
49
|
+
* tool the model never sees.
|
|
50
|
+
*
|
|
51
|
+
* Deliberately not widened to `| undefined` (unlike most optional fields in this port) — this
|
|
52
|
+
* type flows into `core/tools/registration-kit.ts`'s `WirableToolDefinition`, which declares both
|
|
53
|
+
* this field and `actorClassRule` above without `| undefined`. Widening only this catalog's copy
|
|
54
|
+
* would make it structurally incompatible with that shared interface under
|
|
55
|
+
* `exactOptionalPropertyTypes`, the same reason `navigation`'s and `identity`'s catalogs leave
|
|
56
|
+
* these two fields alone.
|
|
57
|
+
*/
|
|
58
|
+
inputSchema?: Readonly<Record<string, unknown>>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The Workspace domain's fixed agent-tool catalog.
|
|
62
|
+
*
|
|
63
|
+
* @complexity O(1) — a fixed, statically-defined list.
|
|
64
|
+
* @overallScore 100
|
|
65
|
+
*/
|
|
66
|
+
export declare function getWorkspaceAgentToolCatalog(): AgentToolDefinition[];
|
|
67
|
+
//# sourceMappingURL=agent-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-tools.d.ts","sourceRoot":"","sources":["../../src/workspace/agent-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,uBAAuB,GAAG,aAAa,CAAC;AAEnF,MAAM,MAAM,uBAAuB,GAAG,sCAAsC,GAAG,WAAW,GAAG,MAAM,CAAC;AAEpG,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,mBAAmB,CAAC;IACjC,aAAa,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,cAAc,CAAC,EAAE,uBAAuB,CAAC;IACzC;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACjD;AA6BD;;;;;GAKG;AACH,wBAAgB,4BAA4B,IAAI,mBAAmB,EAAE,CAsCpE"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The Workspace domain's agent-tool catalog, instantiating this package's shared
|
|
3
|
+
* naming/callability convention (the same shape every other domain catalog in this package
|
|
4
|
+
* already uses).
|
|
5
|
+
*
|
|
6
|
+
* Purpose:
|
|
7
|
+
* A static, in-process catalog describing every agent-callable tool this domain exposes and the
|
|
8
|
+
* permission each one carries. This is the highest-stakes domain wired so far: a host's
|
|
9
|
+
* `workspaceId` is fixed at process composition (a v1 install always has exactly one addressable
|
|
10
|
+
* workspace row), so `create`/`delete` are deliberately excluded
|
|
11
|
+
* outright rather than treated as ordinary CRUD:
|
|
12
|
+
* - `CREATE_WORKSPACE` inserts a row no route can ever address afterwards (every other workspace
|
|
13
|
+
* route resolves strictly against the boot-wired `workspaceId`, never a caller-supplied id)
|
|
14
|
+
* — wiring it would let an agent mint permanently orphaned, unreferenceable rows with no
|
|
15
|
+
* corresponding read/delete path back to them. Zero utility, non-zero clutter/spam surface.
|
|
16
|
+
* - `DELETE_WORKSPACE` is INV-03-guarded to always refuse in v1 (there is only ever one row), but
|
|
17
|
+
* the moment that guard's precondition changes (a second addressable workspace exists), the same
|
|
18
|
+
* tool becomes a lever that can remove the only workspace scope a request can reach — whole-scope,
|
|
19
|
+
* no per-domain undo, the same blast-radius class as a forward database migration or a backup
|
|
20
|
+
* restore. Excluded by design, mirroring those two.
|
|
21
|
+
* `UPDATE_WORKSPACE` is the one write kept: a narrow rename of `name`/`slug` on the single existing,
|
|
22
|
+
* already-addressable workspace, no cascading effects (`id`/`createdAt` immutable by convention —
|
|
23
|
+
* see `update.ts`), the same risk class as `identity_role_rename`.
|
|
24
|
+
*
|
|
25
|
+
* How it relates to the package:
|
|
26
|
+
* A host's server-side tool filter consumes this catalog to decide which tool names an
|
|
27
|
+
* agent session may even see; `authorize()` (the single-evaluator rule below) enforces the actual
|
|
28
|
+
* permission checks at call time — this module only declares the catalog shape, it performs no
|
|
29
|
+
* I/O and no enforcement itself.
|
|
30
|
+
*
|
|
31
|
+
* Architectural role:
|
|
32
|
+
* `workspace` domain logic. No dependencies.
|
|
33
|
+
*/
|
|
34
|
+
/** No arguments — `workspace_get` takes none; it always reports the caller's own boot-wired workspace. */
|
|
35
|
+
const NO_INPUT_SCHEMA = {
|
|
36
|
+
type: "object",
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
required: [],
|
|
39
|
+
properties: {},
|
|
40
|
+
};
|
|
41
|
+
/** `workspace_update`'s input — mirrors `update.ts`'s `UpdateWorkspaceInput` minus `id` (the tool
|
|
42
|
+
* always targets the caller's own boot-wired workspace, exactly like an admin route's
|
|
43
|
+
* `:workspaceId` path param, which is checked against the host's own `workspaceId` and never
|
|
44
|
+
* trusted otherwise). At least one of `name`/`slug` must be present — enforced by `updateWorkspace`
|
|
45
|
+
* itself (`WorkspaceValidationError` on an empty update), not expressible in this package's
|
|
46
|
+
* plain-JSON-Schema-subset convention (no domain catalog uses `anyOf`/`oneOf` today). */
|
|
47
|
+
const UPDATE_WORKSPACE_SCHEMA = {
|
|
48
|
+
type: "object",
|
|
49
|
+
additionalProperties: false,
|
|
50
|
+
required: [],
|
|
51
|
+
properties: {
|
|
52
|
+
name: { type: "string", description: "New workspace name. Omit to leave unchanged. At least one of name/slug is required." },
|
|
53
|
+
slug: {
|
|
54
|
+
type: "string",
|
|
55
|
+
description: "New workspace slug (lowercase letters, numbers, dashes only). Omit to leave unchanged. At least one of name/slug is required.",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* The Workspace domain's fixed agent-tool catalog.
|
|
61
|
+
*
|
|
62
|
+
* @complexity O(1) — a fixed, statically-defined list.
|
|
63
|
+
* @overallScore 100
|
|
64
|
+
*/
|
|
65
|
+
export function getWorkspaceAgentToolCatalog() {
|
|
66
|
+
return [
|
|
67
|
+
{
|
|
68
|
+
name: "workspace_get",
|
|
69
|
+
description: "Reports the caller's own workspace: id, name, slug, and creation time. v1 always has exactly one addressable workspace.",
|
|
70
|
+
sideEffects: "none",
|
|
71
|
+
authorization: { permission: "workspace.manage" },
|
|
72
|
+
inputSchema: NO_INPUT_SCHEMA,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "workspace_update",
|
|
76
|
+
description: "Renames the caller's own workspace: updates name and/or slug. At least one field is required. Does not change the workspace's id or creation time, and has no cascading effects on other domains.",
|
|
77
|
+
sideEffects: "mutates-durable-state",
|
|
78
|
+
authorization: { permission: "workspace.manage" },
|
|
79
|
+
inputSchema: UPDATE_WORKSPACE_SCHEMA,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
// EXCLUDED BY DESIGN, never wired: see this file's header. Inserts a row no other route can
|
|
83
|
+
// ever address (every workspace route resolves strictly against the boot-wired
|
|
84
|
+
// `workspaceId`), so wiring this would only let an agent mint permanently orphaned rows.
|
|
85
|
+
name: "workspace_create",
|
|
86
|
+
description: "Creates a new workspace row. NEVER agent-callable — see file header.",
|
|
87
|
+
sideEffects: "mutates-durable-state",
|
|
88
|
+
authorization: { permission: "workspace.manage" },
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
// EXCLUDED BY DESIGN, never wired: see this file's header. INV-03-guarded to always refuse
|
|
92
|
+
// today (v1 has exactly one workspace row), but the lever itself removes the only addressable
|
|
93
|
+
// workspace scope the moment that guard's precondition ever changes — whole-scope,
|
|
94
|
+
// irreversible, no per-domain undo. Same exclusion class as a forward database migration or a
|
|
95
|
+
// backup restore.
|
|
96
|
+
name: "workspace_delete",
|
|
97
|
+
description: "Deletes a workspace row. NEVER agent-callable — see file header.",
|
|
98
|
+
sideEffects: "mutates-durable-state",
|
|
99
|
+
authorization: { permission: "workspace.manage" },
|
|
100
|
+
},
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=agent-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-tools.js","sourceRoot":"","sources":["../../src/workspace/agent-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AA6BH,0GAA0G;AAC1G,MAAM,eAAe,GAAG;IACtB,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,EAAE;CACN,CAAC;AAEX;;;;;yFAKyF;AACzF,MAAM,uBAAuB,GAAG;IAC9B,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE;QACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,qFAAqF,EAAE;QAC5H,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,+HAA+H;SAC7I;KACF;CACO,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B;IAC1C,OAAO;QACL;YACE,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,yHAAyH;YACtI,WAAW,EAAE,MAAM;YACnB,aAAa,EAAE,EAAE,UAAU,EAAE,kBAAkB,EAAE;YACjD,WAAW,EAAE,eAAe;SAC7B;QACD;YACE,IAAI,EAAE,kBAAkB;YACxB,WAAW,EACT,mMAAmM;YACrM,WAAW,EAAE,uBAAuB;YACpC,aAAa,EAAE,EAAE,UAAU,EAAE,kBAAkB,EAAE;YACjD,WAAW,EAAE,uBAAuB;SACrC;QACD;YACE,4FAA4F;YAC5F,+EAA+E;YAC/E,yFAAyF;YACzF,IAAI,EAAE,kBAAkB;YACxB,WAAW,EAAE,sEAAsE;YACnF,WAAW,EAAE,uBAAuB;YACpC,aAAa,EAAE,EAAE,UAAU,EAAE,kBAAkB,EAAE;SAClD;QACD;YACE,2FAA2F;YAC3F,8FAA8F;YAC9F,mFAAmF;YACnF,8FAA8F;YAC9F,kBAAkB;YAClB,IAAI,EAAE,kBAAkB;YACxB,WAAW,EAAE,kEAAkE;YAC/E,WAAW,EAAE,uBAAuB;YACpC,aAAa,EAAE,EAAE,UAAU,EAAE,kBAAkB,EAAE;SAClD;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { ClockPort, IdGeneratorPort, OutboxPort, UUID } from "../core/ports.js";
|
|
2
|
+
/**
|
|
3
|
+
* @file Workspace creation vertical slice (domain logic).
|
|
4
|
+
*
|
|
5
|
+
* Purpose:
|
|
6
|
+
* Encapsulates business rules for creating a workspace. Also owns the shared
|
|
7
|
+
* `WorkspaceRepoPort` contract and record shape for the whole feature slice
|
|
8
|
+
* (`update.ts`/`delete.ts` import from here rather than duplicating
|
|
9
|
+
* the port) — mirrors `identity/types.ts`+`identity/ports.ts` owning the
|
|
10
|
+
* shared shapes their sibling transition files (`grant-service.ts`) import.
|
|
11
|
+
*
|
|
12
|
+
* How it relates to the package:
|
|
13
|
+
* - Imports abstractions from `../core/ports.js` (no framework/db coupling).
|
|
14
|
+
* - Uses `WorkspaceRepoPort` for persistence and `OutboxPort` for event enqueue.
|
|
15
|
+
* - Is invoked by a host's own admin create-workspace route (moved off the
|
|
16
|
+
* original unauthenticated `POST /workspaces` route in the host's composition root).
|
|
17
|
+
* - Is verified by tests in `./__tests__`.
|
|
18
|
+
*
|
|
19
|
+
* Architectural role:
|
|
20
|
+
* Demonstrates the intended slice pattern:
|
|
21
|
+
* validate -> check constraints -> persist -> enqueue domain event.
|
|
22
|
+
*/
|
|
23
|
+
export interface WorkspaceRecord {
|
|
24
|
+
id: UUID;
|
|
25
|
+
name: string;
|
|
26
|
+
slug: string;
|
|
27
|
+
createdAt: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Workspace persistence contract for this slice. `findById`/`list`/`update`/`delete` were
|
|
31
|
+
* later additions (both adapters — this package's `repo.memory.ts` and a host's own SQLite
|
|
32
|
+
* adapter — implement all seven methods; `insert`/`findBySlug`'s existing contract is unchanged).
|
|
33
|
+
*/
|
|
34
|
+
export interface WorkspaceRepoPort {
|
|
35
|
+
insert(record: WorkspaceRecord): Promise<void>;
|
|
36
|
+
findBySlug(slug: string): Promise<WorkspaceRecord | null>;
|
|
37
|
+
findById(id: UUID): Promise<WorkspaceRecord | null>;
|
|
38
|
+
/** A v1 install always has exactly one row (see `delete.ts`'s header);
|
|
39
|
+
* the port itself is not limited to one. */
|
|
40
|
+
list(): Promise<WorkspaceRecord[]>;
|
|
41
|
+
/** Replaces the full record (id/createdAt immutable by convention — see
|
|
42
|
+
* `update.ts`, which never changes them). */
|
|
43
|
+
update(record: WorkspaceRecord): Promise<void>;
|
|
44
|
+
/** Callers (see `delete.ts`) must apply the last-workspace guard
|
|
45
|
+
* themselves — this port method performs the row deletion only, no business rule. */
|
|
46
|
+
delete(id: UUID): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Shared `name`/`slug` validation — used by both `createWorkspace` below
|
|
50
|
+
* and `updateWorkspace` (`update.ts`) so the two transitions can never drift on what counts as a
|
|
51
|
+
* valid name/slug. Returns the normalized (trimmed name, trimmed+lowercased slug) pair; throws
|
|
52
|
+
* `WorkspaceValidationError` on either being invalid.
|
|
53
|
+
*
|
|
54
|
+
* @complexity O(1) — two regex/trim checks.
|
|
55
|
+
* @overallScore 100
|
|
56
|
+
*/
|
|
57
|
+
export declare function validateWorkspaceNameAndSlug(input: {
|
|
58
|
+
name: string;
|
|
59
|
+
slug: string;
|
|
60
|
+
}): {
|
|
61
|
+
name: string;
|
|
62
|
+
slug: string;
|
|
63
|
+
};
|
|
64
|
+
/** Command payload for workspace creation. */
|
|
65
|
+
export interface CreateWorkspaceInput {
|
|
66
|
+
name: string;
|
|
67
|
+
slug: string;
|
|
68
|
+
}
|
|
69
|
+
/** Dependencies required by the create-workspace slice. */
|
|
70
|
+
export interface CreateWorkspaceDeps {
|
|
71
|
+
idGen: IdGeneratorPort;
|
|
72
|
+
clock: ClockPort;
|
|
73
|
+
repo: WorkspaceRepoPort;
|
|
74
|
+
outbox: OutboxPort;
|
|
75
|
+
}
|
|
76
|
+
/** Required parameters for createWorkspace. */
|
|
77
|
+
export interface CreateWorkspaceRequired {
|
|
78
|
+
deps: CreateWorkspaceDeps;
|
|
79
|
+
input: CreateWorkspaceInput;
|
|
80
|
+
}
|
|
81
|
+
/** Optional parameters for createWorkspace. Reserved for future use. */
|
|
82
|
+
export interface CreateWorkspaceOptional {
|
|
83
|
+
}
|
|
84
|
+
/** Thrown when incoming command data is invalid. */
|
|
85
|
+
export declare class WorkspaceValidationError extends Error {
|
|
86
|
+
}
|
|
87
|
+
/** Thrown when uniqueness constraints are violated. */
|
|
88
|
+
export declare class WorkspaceConflictError extends Error {
|
|
89
|
+
}
|
|
90
|
+
/** Thrown when a `:workspaceId` does not resolve to a row. */
|
|
91
|
+
export declare class WorkspaceNotFoundError extends Error {
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Thrown when `deleteWorkspace` (`delete.ts`) would remove the install's
|
|
95
|
+
* last remaining workspace row. Named distinctly from `WorkspaceConflictError` (a 409, same as this
|
|
96
|
+
* maps to) so a caller can tell "duplicate slug" apart from "would brick the install" without
|
|
97
|
+
* string-matching the message — mirrors this codebase's `GrantExceedsIssuerError` being kept distinct
|
|
98
|
+
* from `IdentityForbiddenError` for the identical reason (typed-reason clarity).
|
|
99
|
+
*/
|
|
100
|
+
export declare class WorkspaceLastRemainingError extends Error {
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Execute create-workspace command.
|
|
104
|
+
*
|
|
105
|
+
* Synchronous path:
|
|
106
|
+
* - validate input
|
|
107
|
+
* - check uniqueness
|
|
108
|
+
* - write workspace record
|
|
109
|
+
*
|
|
110
|
+
* Asynchronous path:
|
|
111
|
+
* - enqueue `workspace.created` domain event to outbox
|
|
112
|
+
*/
|
|
113
|
+
export declare function createWorkspace(required: CreateWorkspaceRequired, _optional?: CreateWorkspaceOptional): Promise<{
|
|
114
|
+
id: UUID;
|
|
115
|
+
}>;
|
|
116
|
+
//# sourceMappingURL=create.d.ts.map
|