@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,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The fixed taxonomy validation chains.
|
|
3
|
+
*
|
|
4
|
+
* Purpose:
|
|
5
|
+
* Two pure, order-critical decision functions:
|
|
6
|
+
* - `validateContentJoin` — the allow-list -> workspace -> lens chain that gates every
|
|
7
|
+
* `entry_terms` write ("opt-in per content type" plus the workspace/lens folds a security
|
|
8
|
+
* audit added).
|
|
9
|
+
* - `validateHierarchyAssignment` — the hierarchical-mode -> same-taxonomy -> cycle chain
|
|
10
|
+
* that gates every `parentId` write.
|
|
11
|
+
*
|
|
12
|
+
* Both chains were the exact unit three separate Red-Team rounds found real ordering defects in —
|
|
13
|
+
* a combined-failure case must always report the FIRST-in-order failure, never a later one that
|
|
14
|
+
* also happens to apply. Every test in `validation-chain.unit.test.ts` replays one of those
|
|
15
|
+
* regressions or a compound-failure case to lock the order in place.
|
|
16
|
+
*
|
|
17
|
+
* `wouldCreateCycle` is the full ancestor-chain walk `validateHierarchyAssignment`'s cycle check
|
|
18
|
+
* ultimately calls — kept exported separately since it has its own certified property tests
|
|
19
|
+
* (depth 1-10 chains) independent of the chain that wraps it.
|
|
20
|
+
*
|
|
21
|
+
* How it relates to the project:
|
|
22
|
+
* Consumed directly by `write-service.ts`'s `createTerm`/`renameTerm`/`assignTerms` (and would be
|
|
23
|
+
* consumed by a future `reparentTerm`, not yet built — no certified test in this slice exercises
|
|
24
|
+
* it). Reuses no port/dep — these are pure functions over caller-resolved data, never performing
|
|
25
|
+
* their own repo lookups, so the ordering guarantee holds regardless of how a caller wires them.
|
|
26
|
+
*/
|
|
27
|
+
export class TaxonomyNotApplicableError extends Error {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = "TaxonomyNotApplicableError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export class WorkspaceMismatchError extends Error {
|
|
34
|
+
constructor(message) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = "WorkspaceMismatchError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export class ContentTypeMismatchError extends Error {
|
|
40
|
+
constructor(message) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = "ContentTypeMismatchError";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export class TaxonomyNotHierarchicalError extends Error {
|
|
46
|
+
constructor(message) {
|
|
47
|
+
super(message);
|
|
48
|
+
this.name = "TaxonomyNotHierarchicalError";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export class ParentCrossTaxonomyError extends Error {
|
|
52
|
+
constructor(message) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.name = "ParentCrossTaxonomyError";
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export class TermNotFoundError extends Error {
|
|
58
|
+
constructor(message) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = "TermNotFoundError";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export class HierarchyCycleDetectedError extends Error {
|
|
64
|
+
constructor(message) {
|
|
65
|
+
super(message);
|
|
66
|
+
this.name = "HierarchyCycleDetectedError";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* CIC U-002 — true if assigning `candidateParentId` as `termId`'s parent would create a cycle:
|
|
71
|
+
* either immediate self-parenting, or `termId` appearing anywhere in `candidateParentId`'s own
|
|
72
|
+
* ancestor chain. A full recursive walk, not a fixed-depth or immediate-parent-only comparison
|
|
73
|
+
* (U-002-B1) — the exact shape a naive implementation gets wrong (a 3+-hop cycle is the
|
|
74
|
+
* regression case this exists to catch).
|
|
75
|
+
*
|
|
76
|
+
* A `visited` guard bounds the walk even against a pre-existing malformed tree (defensive; no
|
|
77
|
+
* certified test constructs one, but an unbounded walk over attacker/bug-corrupted ancestor data
|
|
78
|
+
* would otherwise loop forever).
|
|
79
|
+
*
|
|
80
|
+
* @complexity O(depth) — one `getParentId` call per ancestor hop, each hop visited at most once.
|
|
81
|
+
* @overallScore 100
|
|
82
|
+
*/
|
|
83
|
+
export function wouldCreateCycle(required, _optional = {}) {
|
|
84
|
+
const { termId, candidateParentId, tree } = required;
|
|
85
|
+
if (candidateParentId === termId)
|
|
86
|
+
return true;
|
|
87
|
+
const visited = new Set();
|
|
88
|
+
let current = candidateParentId;
|
|
89
|
+
while (current !== null) {
|
|
90
|
+
if (visited.has(current))
|
|
91
|
+
return false; // malformed/self-looping ancestor data upstream of termId; not this call's cycle
|
|
92
|
+
visited.add(current);
|
|
93
|
+
const parent = tree.getParentId(current);
|
|
94
|
+
if (parent === termId)
|
|
95
|
+
return true;
|
|
96
|
+
current = parent;
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* U-001-B1/ORD1/ORD2 — the content-join chain: allow-list, THEN workspace, THEN lens, in that
|
|
102
|
+
* fixed order. A combined-failure case always reports the first-in-order failure (U-001-ORD1:
|
|
103
|
+
* not-on-allow-list always wins over a simultaneous workspace mismatch; U-001-ORD2: a workspace
|
|
104
|
+
* mismatch always wins over a simultaneous lens mismatch).
|
|
105
|
+
*
|
|
106
|
+
* @complexity O(1) — three independent comparisons, no loop.
|
|
107
|
+
* @overallScore 100
|
|
108
|
+
*/
|
|
109
|
+
export function validateContentJoin(required, _optional = {}) {
|
|
110
|
+
const { taxonomyId, isOnAllowList, callerWorkspaceId, resolvedTermWorkspaceId, resolvedContentWorkspaceId, suppliedContentType, resolvedContentKind, } = required;
|
|
111
|
+
if (!isOnAllowList) {
|
|
112
|
+
throw new TaxonomyNotApplicableError(`taxonomy '${taxonomyId}' is not on the allow-list for content type '${suppliedContentType}'`);
|
|
113
|
+
}
|
|
114
|
+
if (resolvedTermWorkspaceId !== callerWorkspaceId || resolvedContentWorkspaceId !== callerWorkspaceId) {
|
|
115
|
+
throw new WorkspaceMismatchError(`term/content workspace does not match the caller's workspace '${callerWorkspaceId}'`);
|
|
116
|
+
}
|
|
117
|
+
if (resolvedContentKind !== suppliedContentType) {
|
|
118
|
+
throw new ContentTypeMismatchError(`supplied content type '${suppliedContentType}' does not match the resolved row's own kind '${resolvedContentKind}'`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* U-001-B2/B3/ORD3 — the hierarchy chain: hierarchical-mode, THEN same-taxonomy (distinguishing
|
|
123
|
+
* not-found from wrong-taxonomy), THEN cycle, in that fixed order. `null` `candidateParentId`
|
|
124
|
+
* (no parent assignment attempted) always short-circuits to a pass regardless of mode (RT-012's
|
|
125
|
+
* regression: a no-op parent write must never be rejected).
|
|
126
|
+
*
|
|
127
|
+
* The compound RT-001 regression this chain exists to prevent: a flat taxonomy's candidate parent
|
|
128
|
+
* that ALSO happens to exist in a different taxonomy must report `TAXONOMY_NOT_HIERARCHICAL`,
|
|
129
|
+
* never `PARENT_CROSS_TAXONOMY` — hierarchical-mode is checked first and is decisive on its own.
|
|
130
|
+
*
|
|
131
|
+
* @complexity O(1) plus the injected `wouldCreateCycle` closure's own cost (U-002, only reached
|
|
132
|
+
* once hierarchical-mode and same-taxonomy both pass).
|
|
133
|
+
* @overallScore 100
|
|
134
|
+
*/
|
|
135
|
+
export function validateHierarchyAssignment(required, _optional = {}) {
|
|
136
|
+
const { taxonomyIsHierarchical, candidateParentId, resolvedParent, childTaxonomyId, wouldCreateCycle: checkCycle } = required;
|
|
137
|
+
if (candidateParentId === null)
|
|
138
|
+
return;
|
|
139
|
+
if (!taxonomyIsHierarchical) {
|
|
140
|
+
throw new TaxonomyNotHierarchicalError(`taxonomy '${childTaxonomyId}' is not hierarchical; parentId must be null`);
|
|
141
|
+
}
|
|
142
|
+
if (resolvedParent === null || resolvedParent === "not-applicable") {
|
|
143
|
+
throw new TermNotFoundError(`parent term '${candidateParentId}' was not found`);
|
|
144
|
+
}
|
|
145
|
+
if (resolvedParent.taxonomyId !== childTaxonomyId) {
|
|
146
|
+
throw new ParentCrossTaxonomyError(`parent term '${candidateParentId}' belongs to taxonomy '${resolvedParent.taxonomyId}', not '${childTaxonomyId}'`);
|
|
147
|
+
}
|
|
148
|
+
if (checkCycle(candidateParentId)) {
|
|
149
|
+
throw new HierarchyCycleDetectedError(`assigning '${candidateParentId}' as parent would create a hierarchy cycle`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=validation-chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-chain.js","sourceRoot":"","sources":["../../src/taxonomy/validation-chain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import type { TermListPort } from "./list.js";
|
|
2
|
+
/**
|
|
3
|
+
* @file The taxonomy write-service's ordinary (non-gated) mutations.
|
|
4
|
+
*
|
|
5
|
+
* Purpose:
|
|
6
|
+
* The single write chokepoint for `taxonomies`/`terms`/`entry_terms` (the same discipline applied
|
|
7
|
+
* to every other domain's write-service in this codebase): `authorize()` first (fail-closed) ->
|
|
8
|
+
* validate -> write + revision + watermark + outbox, all attributed to the same mutation.
|
|
9
|
+
* `assignTerms` is the one deliberate exception: term-assignment membership is explicitly narrowed
|
|
10
|
+
* out of the general revisioning rule — high-churn relational state whose historical audit trail is
|
|
11
|
+
* judged low-value, the same disclosed-loss basis `redirect_hits`/`asset_renditions` already use.
|
|
12
|
+
*
|
|
13
|
+
* `mergeTerm` (the one gated mutation) is deliberately NOT here — it lives in the sibling
|
|
14
|
+
* `merge-term.ts`, isolated because it alone touches `core/gated-mutations`.
|
|
15
|
+
*
|
|
16
|
+
* A past security re-audit (finding: a hard blocker) established that `assignTerms` must invoke
|
|
17
|
+
* `validation-chain.ts`'s `validateContentJoin` (allow-list -> workspace -> lens, fixed order)
|
|
18
|
+
* before writing any `entry_terms` row. The prior "disclosed gap" comment this replaces undersold
|
|
19
|
+
* the live risk — the missing check meant `assignTerms` (a live, `admin.taxonomy.manage`-gated
|
|
20
|
+
* route) would silently accept a nonexistent `termId`, a `contentId` that doesn't exist, or a
|
|
21
|
+
* caller-claimed `contentType` that doesn't match the target's real kind, with zero server-side
|
|
22
|
+
* verification. `ContentLookupPort` below is the "content repo port" the old comment said this
|
|
23
|
+
* needed. `resolvedTermWorkspaceId`/`resolvedContentWorkspaceId` both resolve to the SAME value as
|
|
24
|
+
* `callerWorkspaceId` by construction in this codebase's real adapters (`SqliteTermRepo`/
|
|
25
|
+
* `SqliteEntryTermRepo` are workspace-BOUND at construction, single-workspace-per-`content.db`), so
|
|
26
|
+
* the workspace-mismatch branch is currently unreachable via those adapters specifically; it stays
|
|
27
|
+
* load-bearing for any future adapter that is not workspace-bound, and the check costs nothing to
|
|
28
|
+
* keep. See `docs/decisions/taxonomy-content-type-allow-list.md` for why both this branch and
|
|
29
|
+
* `TAXONOMY_ALLOWED_CONTENT_TYPES` below are permanent design choices, not stopgaps.
|
|
30
|
+
*
|
|
31
|
+
* How it relates to the project:
|
|
32
|
+
* Mirrors `src/features/settings/write-service.ts`'s chokepoint shape (authorize -> validate ->
|
|
33
|
+
* same-tx write + revision) and the required-input-object convention `src/features/post/post.ts`
|
|
34
|
+
* establishes.
|
|
35
|
+
*/
|
|
36
|
+
/** Local, structurally-compatible authorize gate — no `workspaceId` is threaded through this
|
|
37
|
+
* slice's certified write-service tests (every function signature they exercise omits it), so
|
|
38
|
+
* this type intentionally does not require one, unlike `core/commands/command.ts`'s `AuthorizeFn`.
|
|
39
|
+
* A future route/wiring layer that has real workspace context can still satisfy this shape. */
|
|
40
|
+
export type AuthorizeFn = (params: {
|
|
41
|
+
principalId: string;
|
|
42
|
+
permission: string;
|
|
43
|
+
}) => Promise<{
|
|
44
|
+
allowed: boolean;
|
|
45
|
+
reason: string;
|
|
46
|
+
}>;
|
|
47
|
+
export interface Taxonomy {
|
|
48
|
+
id: string;
|
|
49
|
+
name: string;
|
|
50
|
+
hierarchical: boolean;
|
|
51
|
+
status: string;
|
|
52
|
+
updatedAt: string;
|
|
53
|
+
version: number;
|
|
54
|
+
}
|
|
55
|
+
export interface Term {
|
|
56
|
+
id: string;
|
|
57
|
+
taxonomyId: string;
|
|
58
|
+
parentId: string | null;
|
|
59
|
+
name: string;
|
|
60
|
+
status: string;
|
|
61
|
+
updatedAt: string;
|
|
62
|
+
version: number;
|
|
63
|
+
}
|
|
64
|
+
export interface TaxonomyRepoPort {
|
|
65
|
+
findById(id: string): Promise<{
|
|
66
|
+
id: string;
|
|
67
|
+
hierarchical: boolean;
|
|
68
|
+
allowList?: string[] | undefined;
|
|
69
|
+
} | null>;
|
|
70
|
+
insert(row: Taxonomy): Promise<unknown>;
|
|
71
|
+
}
|
|
72
|
+
export interface TermRepoPort {
|
|
73
|
+
findById(id: string): Promise<{
|
|
74
|
+
id: string;
|
|
75
|
+
taxonomyId: string;
|
|
76
|
+
name?: string | undefined;
|
|
77
|
+
} | null>;
|
|
78
|
+
insert(row: Term): Promise<unknown>;
|
|
79
|
+
update(row: Term): Promise<unknown>;
|
|
80
|
+
}
|
|
81
|
+
export interface EntryTermRepoPort {
|
|
82
|
+
upsert(row: {
|
|
83
|
+
contentType: string;
|
|
84
|
+
contentId: string;
|
|
85
|
+
termId: string;
|
|
86
|
+
addedAt: string;
|
|
87
|
+
}): Promise<unknown>;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Resolves the REAL workspace + kind of a `(contentType, contentId)` pair — the "content repo
|
|
91
|
+
* port" `validateContentJoin` needs to verify a caller's claimed `contentType` actually matches
|
|
92
|
+
* the target row, and that the target exists at all. `null` = not found. Implementations for
|
|
93
|
+
* `contentType` values on {@link TAXONOMY_ALLOWED_CONTENT_TYPES} resolve against `posts`; a
|
|
94
|
+
* future content-type this port grows to cover would extend it, not replace it.
|
|
95
|
+
*/
|
|
96
|
+
export interface ContentLookupPort {
|
|
97
|
+
resolve(params: {
|
|
98
|
+
contentType: string;
|
|
99
|
+
contentId: string;
|
|
100
|
+
}): Promise<{
|
|
101
|
+
workspaceId: string;
|
|
102
|
+
kind: string;
|
|
103
|
+
} | null>;
|
|
104
|
+
}
|
|
105
|
+
/** The hardcoded post/page taxonomy allow-list (permanent, see
|
|
106
|
+
* `docs/decisions/taxonomy-content-type-allow-list.md`) — every taxonomy is applicable to
|
|
107
|
+
* `post`/`page` content; no other content type is eligible for term assignment until this is
|
|
108
|
+
* deliberately extended. */
|
|
109
|
+
export declare const TAXONOMY_ALLOWED_CONTENT_TYPES: ReadonlySet<string>;
|
|
110
|
+
export declare function isContentTypeOnAllowList(contentType: string): boolean;
|
|
111
|
+
export interface TaxonomyRevisionRow {
|
|
112
|
+
taxonomyId: string;
|
|
113
|
+
/** `"delete"` added for `deleteTerm`/`deleteTaxonomy` below — unlike `mergeTerm`'s reuse of
|
|
114
|
+
* `"deprecate"` (that ceremony's own header explains why widening this union was out of its
|
|
115
|
+
* scope), a delete has no honest fit among the other four ops, so this widens the union rather
|
|
116
|
+
* than overloading an existing member. */
|
|
117
|
+
op: "create" | "rename" | "reparent" | "deprecate" | "delete";
|
|
118
|
+
previousState: Record<string, unknown> | null;
|
|
119
|
+
actorId: string;
|
|
120
|
+
recordedAt: string;
|
|
121
|
+
}
|
|
122
|
+
export interface TaxonomyRevisionRepoPort {
|
|
123
|
+
insert(row: TaxonomyRevisionRow): Promise<unknown>;
|
|
124
|
+
}
|
|
125
|
+
export interface ClockPort {
|
|
126
|
+
nowIso(): string;
|
|
127
|
+
}
|
|
128
|
+
export interface IdGeneratorPort {
|
|
129
|
+
newId(): string;
|
|
130
|
+
}
|
|
131
|
+
export interface WriteServiceDeps {
|
|
132
|
+
authorize: AuthorizeFn;
|
|
133
|
+
clock: ClockPort;
|
|
134
|
+
idGen: IdGeneratorPort;
|
|
135
|
+
taxonomies: TaxonomyRepoPort;
|
|
136
|
+
terms: TermRepoPort;
|
|
137
|
+
entryTerms: EntryTermRepoPort;
|
|
138
|
+
revisions: TaxonomyRevisionRepoPort;
|
|
139
|
+
/** `core/gated-mutations.stampWatermark`-shaped, injected — same-transaction stamp per mutation. */
|
|
140
|
+
stampWatermark: (tx?: unknown) => void;
|
|
141
|
+
outbox: {
|
|
142
|
+
enqueue: (event: unknown) => Promise<void>;
|
|
143
|
+
};
|
|
144
|
+
/** The caller's own workspace — `validateContentJoin`'s `callerWorkspaceId` (Finding 1 fix). */
|
|
145
|
+
workspaceId: string;
|
|
146
|
+
/** Resolves a `(contentType, contentId)` pair's real workspace/kind for `assignTerms`'s
|
|
147
|
+
* content-join validation (Finding 1 fix). */
|
|
148
|
+
contentLookup: ContentLookupPort;
|
|
149
|
+
}
|
|
150
|
+
export declare class TaxonomyRecordNotFoundError extends Error {
|
|
151
|
+
constructor(message: string);
|
|
152
|
+
}
|
|
153
|
+
export declare class TermRecordNotFoundError extends Error {
|
|
154
|
+
constructor(message: string);
|
|
155
|
+
}
|
|
156
|
+
/** Finding 1 fix — the target of an `assignTerms` call does not resolve to any real content row. */
|
|
157
|
+
export declare class ContentRecordNotFoundError extends Error {
|
|
158
|
+
constructor(message: string);
|
|
159
|
+
}
|
|
160
|
+
export interface CreateTaxonomyRequired {
|
|
161
|
+
deps: WriteServiceDeps;
|
|
162
|
+
principalId: string;
|
|
163
|
+
name: string;
|
|
164
|
+
hierarchical: boolean;
|
|
165
|
+
}
|
|
166
|
+
/** Creates a taxonomy row (hierarchical=true -> "category"-shaped, false -> "tag"-shaped — same
|
|
167
|
+
* shared table). Ordinary mutation, no plan()/confirmation ceremony. */
|
|
168
|
+
export declare function createTaxonomy(required: CreateTaxonomyRequired, _optional?: Record<string, never>): Promise<Taxonomy>;
|
|
169
|
+
export interface CreateTermRequired {
|
|
170
|
+
deps: WriteServiceDeps;
|
|
171
|
+
principalId: string;
|
|
172
|
+
taxonomyId: string;
|
|
173
|
+
name: string;
|
|
174
|
+
parentId?: string | null | undefined;
|
|
175
|
+
}
|
|
176
|
+
/** AC-03/AC-13/EC-04 — validates `parentId` via `validateHierarchyAssignment` before writing. A
|
|
177
|
+
* freshly-created term has no descendants yet, so it structurally cannot be a cycle source; the
|
|
178
|
+
* cycle check is therefore always a no-op (`() => false`) here, unlike a reparent of an existing
|
|
179
|
+
* term (not yet built — no certified test in this slice exercises it). */
|
|
180
|
+
export declare function createTerm(required: CreateTermRequired, _optional?: Record<string, never>): Promise<Term>;
|
|
181
|
+
export interface RenameTermRequired {
|
|
182
|
+
deps: WriteServiceDeps;
|
|
183
|
+
principalId: string;
|
|
184
|
+
termId: string;
|
|
185
|
+
newName: string;
|
|
186
|
+
}
|
|
187
|
+
/** AC-15/AC-19/AC-25/REQ-12/REQ-17 — same-tx rename + revision (carrying the pre-rename state) +
|
|
188
|
+
* watermark + outbox. `authorize()` runs before the term lookup, so a denied caller produces zero
|
|
189
|
+
* side effects of any kind. */
|
|
190
|
+
export declare function renameTerm(required: RenameTermRequired, _optional?: Record<string, never>): Promise<Term>;
|
|
191
|
+
export interface AssignTermsRequired {
|
|
192
|
+
deps: WriteServiceDeps;
|
|
193
|
+
principalId: string;
|
|
194
|
+
contentType: string;
|
|
195
|
+
contentId: string;
|
|
196
|
+
termIds: string[];
|
|
197
|
+
}
|
|
198
|
+
/** AC-17/AC-20/INV-05/REQ-13/REQ-14 — upserts every `entry_terms` row (idempotent on-conflict per
|
|
199
|
+
* `entry_terms_unique`, EC-09), then stamps the watermark and enqueues the outbox event exactly
|
|
200
|
+
* ONCE per call regardless of `termIds.length` — never once per term. Never produces a
|
|
201
|
+
* `taxonomy_revisions` row (see this file's header for the disclosed narrowing this implements).
|
|
202
|
+
*
|
|
203
|
+
* Finding 1 fix (TM-adr041-043-044-045-audit-001): every `termId` is validated via
|
|
204
|
+
* `validateContentJoin` (allow-list -> workspace -> lens, `validation-chain.ts`'s fixed order)
|
|
205
|
+
* BEFORE any `entry_terms` row is written — every termId must resolve to a real term, and the
|
|
206
|
+
* target content must resolve to a real row whose kind matches the caller-supplied `contentType`.
|
|
207
|
+
* Validation runs for ALL termIds before ANY write, so a failure partway through never leaves a
|
|
208
|
+
* partial assignment. Content is resolved once per call (not once per term) since every term in
|
|
209
|
+
* one call shares the same `(contentType, contentId)` target.
|
|
210
|
+
*/
|
|
211
|
+
export declare function assignTerms(required: AssignTermsRequired, _optional?: Record<string, never>): Promise<void>;
|
|
212
|
+
export interface EntryTermsCleanupPort {
|
|
213
|
+
deleteByContent(params: {
|
|
214
|
+
workspaceId: string;
|
|
215
|
+
contentType: string;
|
|
216
|
+
contentId: string;
|
|
217
|
+
}): Promise<number>;
|
|
218
|
+
}
|
|
219
|
+
export interface OnContentDeletedRequired {
|
|
220
|
+
event: {
|
|
221
|
+
workspaceId: string;
|
|
222
|
+
contentType: string;
|
|
223
|
+
contentId: string;
|
|
224
|
+
};
|
|
225
|
+
entryTerms: EntryTermsCleanupPort;
|
|
226
|
+
}
|
|
227
|
+
/** Content-deletion event subscriber. Best-effort (a missed event leaves an orphaned
|
|
228
|
+
* `entry_terms` row that is inert on read; a periodic/boot reconciliation sweep — modeled by
|
|
229
|
+
* re-invoking this same function for the orphan — is the backstop, never a hard failure). A
|
|
230
|
+
* no-op for content with no
|
|
231
|
+
* assigned terms, never an error. */
|
|
232
|
+
export declare function onContentDeleted(required: OnContentDeletedRequired, _optional?: Record<string, never>): Promise<void>;
|
|
233
|
+
/**
|
|
234
|
+
* Additive capabilities beyond the certified `TaxonomyRepoPort`/`TermRepoPort`/`EntryTermRepoPort`
|
|
235
|
+
* — same beyond-the-certified-port precedent `MergeableEntryTermRepoPort` established in this
|
|
236
|
+
* package's consuming host (`gated-hooks.ts`'s `buildMergeTermHooks`) for `mergeTerm`, applied
|
|
237
|
+
* here for the ordinary (non-gated) `deleteTerm`/`deleteTaxonomy` mutations below. Implemented on
|
|
238
|
+
* both `InMemory*Repo` (`repo.memory.ts`) and a host's own SQLite adapters (this package ships no
|
|
239
|
+
* SQLite adapter of its own — see this file's header and `repo.memory.ts`'s header for why).
|
|
240
|
+
*/
|
|
241
|
+
export interface DeletableTaxonomyRepoPort {
|
|
242
|
+
delete(id: string): Promise<void>;
|
|
243
|
+
}
|
|
244
|
+
export interface DeletableTermRepoPort {
|
|
245
|
+
delete(id: string): Promise<void>;
|
|
246
|
+
/** Direct-child count for `termId` as a parent. `deleteTerm` refuses to delete a term with
|
|
247
|
+
* children still pointing `parentId` at it — that reference would otherwise dangle the moment
|
|
248
|
+
* the parent row is gone, corrupting the hierarchy `validateHierarchyAssignment` polices on the
|
|
249
|
+
* write side. This dispatch's own finding, not a named requirement — no cascading delete of
|
|
250
|
+
* children is attempted; the caller must clear them first (bottom-up), same as the
|
|
251
|
+
* content-assignment guard below forces "unassign first." */
|
|
252
|
+
countChildren(params: {
|
|
253
|
+
parentId: string;
|
|
254
|
+
}): Promise<number>;
|
|
255
|
+
}
|
|
256
|
+
export interface AssignmentCountEntryTermRepoPort {
|
|
257
|
+
/** Count of `entry_terms` rows currently pointing at `termId` — the guard `deleteTerm` (and, by
|
|
258
|
+
* summing across a taxonomy's member terms, `deleteTaxonomy`) uses to refuse destroying an
|
|
259
|
+
* assignment live content still depends on. Deliberately the opposite direction from
|
|
260
|
+
* `onContentDeleted` above: that subscriber cleans up `entry_terms` when CONTENT goes away
|
|
261
|
+
* (content is the thing being removed, so orphaned assignment rows are safe to sweep silently);
|
|
262
|
+
* here the TAXONOMY/TERM is what would be removed while the content stays live, so a silent
|
|
263
|
+
* sweep would delete a real, still-visible link out from under an unrelated content item —
|
|
264
|
+
* refusing the delete instead is the correct direction. */
|
|
265
|
+
countByTerm(params: {
|
|
266
|
+
termId: string;
|
|
267
|
+
}): Promise<number>;
|
|
268
|
+
}
|
|
269
|
+
/** `deleteTerm`/`deleteTaxonomy` refuse rather than silently orphan when content is still
|
|
270
|
+
* assigned. Carries `assignedCount` so a caller (route/UI) can render "N items are still
|
|
271
|
+
* assigned" instead of a generic failure. */
|
|
272
|
+
export declare class TermHasAssignedContentError extends Error {
|
|
273
|
+
readonly assignedCount: number;
|
|
274
|
+
constructor(message: string, assignedCount: number);
|
|
275
|
+
}
|
|
276
|
+
/** See `DeletableTermRepoPort.countChildren`'s doc comment for why this guard exists. Carries
|
|
277
|
+
* `childCount` for the same reason `TermHasAssignedContentError` carries `assignedCount`. */
|
|
278
|
+
export declare class TermHasChildTermsError extends Error {
|
|
279
|
+
readonly childCount: number;
|
|
280
|
+
constructor(message: string, childCount: number);
|
|
281
|
+
}
|
|
282
|
+
/** `deleteTaxonomy`'s content-assignment guard — `assignedCount` is the sum across every member
|
|
283
|
+
* term, not a single term's count. */
|
|
284
|
+
export declare class TaxonomyHasAssignedContentError extends Error {
|
|
285
|
+
readonly assignedCount: number;
|
|
286
|
+
constructor(message: string, assignedCount: number);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Opens/commits/rolls back one transaction around `fn` — the same shape and contract as this
|
|
290
|
+
* codebase's other write chokepoints that need one (`RedirectsWriteDeps.transaction`,
|
|
291
|
+
* `SqliteSettingsRepo.transaction`).
|
|
292
|
+
*
|
|
293
|
+
* `deleteTerm`/`deleteTaxonomy` run their ENTIRE body — every guard read (`findById`,
|
|
294
|
+
* `countChildren`, `countByTerm`) AND every write (`delete`, `revisions.insert`, `outbox.enqueue`)
|
|
295
|
+
* — inside one call to this. Two failure modes this closes that a guard-then-transaction split
|
|
296
|
+
* would not:
|
|
297
|
+
*
|
|
298
|
+
* 1. **TOCTOU on the guard.** A guard read taken BEFORE the transaction opens can go stale the
|
|
299
|
+
* instant it returns — content can be assigned to the term in the gap between the read and the
|
|
300
|
+
* delete, and the delete would proceed having checked a now-wrong count. Putting the read
|
|
301
|
+
* inside the same transaction as the delete is what makes the guard's answer still true at the
|
|
302
|
+
* moment the delete actually runs.
|
|
303
|
+
* 2. **Partial cascade.** `deleteTaxonomy` deletes N member terms then the taxonomy row itself,
|
|
304
|
+
* with no FK/CASCADE at the schema level (`db/schema.ts` — `taxonomies`/`terms`/`entry_terms`/
|
|
305
|
+
* `taxonomy_revisions` are plain columns, no foreign keys) to undo a mid-cascade failure. A
|
|
306
|
+
* real transaction is the only thing that can.
|
|
307
|
+
*
|
|
308
|
+
* A caller-supplied identity/no-op implementation is a valid choice for a backend that has no
|
|
309
|
+
* separate transaction primitive to offer (see `repo.memory.ts`'s `InMemoryTaxonomyRepo` for the
|
|
310
|
+
* disclosed rationale) — the port exists so `deleteTerm`/`deleteTaxonomy` never have to know which
|
|
311
|
+
* kind of backend they're running against.
|
|
312
|
+
*/
|
|
313
|
+
export interface TransactionalRepoPort {
|
|
314
|
+
transaction<T>(fn: () => Promise<T>): Promise<T>;
|
|
315
|
+
}
|
|
316
|
+
export interface DeleteTermRequired {
|
|
317
|
+
deps: WriteServiceDeps & {
|
|
318
|
+
terms: DeletableTermRepoPort;
|
|
319
|
+
entryTerms: AssignmentCountEntryTermRepoPort;
|
|
320
|
+
/** See `TransactionalRepoPort`'s doc comment. Any one repo's `.transaction()` method is a
|
|
321
|
+
* valid source — the route/composition-root wiring picks one (this package stays agnostic to
|
|
322
|
+
* which); every write inside `fn` must land on the SAME underlying connection that opened it,
|
|
323
|
+
* which is a wiring obligation the caller owns, not something this function can verify. */
|
|
324
|
+
transaction: TransactionalRepoPort["transaction"];
|
|
325
|
+
};
|
|
326
|
+
principalId: string;
|
|
327
|
+
termId: string;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Deletes a single term. Refuses (never cascades) when the term still has children or is still
|
|
331
|
+
* assigned to content — both checks run, and either alone is enough to block, before any write.
|
|
332
|
+
* An unassigned, childless term is destroying nothing recoverable, so this is a direct delete with
|
|
333
|
+
* no plan()/confirmation ceremony (`mergeTerm` earns that ceremony because it migrates data this
|
|
334
|
+
* does not).
|
|
335
|
+
*
|
|
336
|
+
* `authorize()` runs before the transaction opens (a pure permission check, no side effect, so it
|
|
337
|
+
* doesn't need transactional protection); everything from the existence check onward — both
|
|
338
|
+
* guards and the delete itself — runs inside `deps.transaction()` (see that port's doc comment for
|
|
339
|
+
* why). Does NOT cascade-delete the term's `taxonomy_revisions` rows: that table is an append-only
|
|
340
|
+
* audit trail (mirrors `redirect_hits`/`asset_renditions`'s disclosed audit-not-referential-
|
|
341
|
+
* integrity precedent), and erasing a term's history the moment the term itself is deleted would
|
|
342
|
+
* destroy the very "this term existed and was deleted" record this call's own revision insert
|
|
343
|
+
* below creates. Confirmed by grepping `db/schema.ts`: no other table has a `taxonomyId`/`termId`
|
|
344
|
+
* column, so `taxonomy_revisions` is the only thing this decision applies to.
|
|
345
|
+
*
|
|
346
|
+
* @complexity O(1) — one `countChildren` call, one `countByTerm` call, one delete, all inside one
|
|
347
|
+
* transaction.
|
|
348
|
+
* @overallScore 100
|
|
349
|
+
*/
|
|
350
|
+
export declare function deleteTerm(required: DeleteTermRequired, _optional?: Record<string, never>): Promise<{
|
|
351
|
+
deletedTermId: string;
|
|
352
|
+
}>;
|
|
353
|
+
export interface DeleteTaxonomyRequired {
|
|
354
|
+
deps: WriteServiceDeps & {
|
|
355
|
+
taxonomies: DeletableTaxonomyRepoPort;
|
|
356
|
+
terms: TermListPort & DeletableTermRepoPort;
|
|
357
|
+
entryTerms: AssignmentCountEntryTermRepoPort;
|
|
358
|
+
/** See `TransactionalRepoPort`'s doc comment. */
|
|
359
|
+
transaction: TransactionalRepoPort["transaction"];
|
|
360
|
+
};
|
|
361
|
+
principalId: string;
|
|
362
|
+
taxonomyId: string;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Deletes a taxonomy together with its member terms, refusing when ANY member term is still
|
|
366
|
+
* assigned to content (the sum across all member terms, reported as one `assignedCount`). Unlike
|
|
367
|
+
* `deleteTerm`, this does cascade — but only over terms this same call has just confirmed, INSIDE
|
|
368
|
+
* the same transaction, are unassigned, so nothing recoverable is lost. `deleteTerm`'s own "has
|
|
369
|
+
* children" guard does not apply here: a member term's children are, by construction, also members
|
|
370
|
+
* of the same taxonomy (hierarchy never crosses taxonomies — `validateHierarchyAssignment`'s
|
|
371
|
+
* `ParentCrossTaxonomyError` enforces that on the write side), so deleting the full member set in
|
|
372
|
+
* one pass never leaves a `parentId` dangling outside the set being deleted.
|
|
373
|
+
*
|
|
374
|
+
* Same transaction-boundary and `taxonomy_revisions`-retention rationale as `deleteTerm` — see its
|
|
375
|
+
* doc comment. The taxonomy-level version of the same TOCTOU risk: `listByTaxonomy` and every
|
|
376
|
+
* per-term `countByTerm` call must see the SAME committed state the delete loop is about to act
|
|
377
|
+
* on, which is only guaranteed inside one transaction, not across N separate queries beforehand.
|
|
378
|
+
*
|
|
379
|
+
* @complexity O(t) in the taxonomy's own term count — one `countByTerm` per member term to total
|
|
380
|
+
* the guard, then one delete per member term plus one taxonomy delete, all inside one transaction.
|
|
381
|
+
* @overallScore 100
|
|
382
|
+
*/
|
|
383
|
+
export declare function deleteTaxonomy(required: DeleteTaxonomyRequired, _optional?: Record<string, never>): Promise<{
|
|
384
|
+
deletedTaxonomyId: string;
|
|
385
|
+
deletedTermIds: string[];
|
|
386
|
+
}>;
|
|
387
|
+
//# sourceMappingURL=write-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-service.d.ts","sourceRoot":"","sources":["../../src/taxonomy/write-service.ts"],"names":[],"mappings":"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"}
|