@happyvertical/smrt-approvals 0.57.36 → 0.57.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { APPROVAL_EVENT_TYPES, APPROVAL_PRINCIPAL_TYPES, APPROVAL_STATUSES, ApprovalError, approvalPrincipalFromPermissions } from "./types.js";
2
- import { ObjectRegistry, SmrtCollection, SmrtObject, appendChange, field, foreignKey, isEmbeddedDatabase, isUniqueViolationError, smrt, withEmbeddedWriteQueue, withEmbeddedWriteTransaction } from "@happyvertical/smrt-core";
2
+ import { ObjectRegistry, SmrtCollection, SmrtObject, SmrtRecipe, appendChange, field, foreignKey, isEmbeddedDatabase, isUniqueViolationError, smrt, withEmbeddedWriteQueue, withEmbeddedWriteTransaction } from "@happyvertical/smrt-core";
3
3
  import { registerPermissionDefinitions } from "@happyvertical/smrt-users";
4
4
  import { TenantScoped, getTenantId, isSystemContext, tenantId, withTenant } from "@happyvertical/smrt-tenancy";
5
5
  //#region src/__smrt-register__.ts
6
- ObjectRegistry.registerPackageManifest(JSON.parse(`{"version":"1.0.0","timestamp":0,"packageName":"@happyvertical/smrt-approvals","packageVersion":"0.57.36","objects":{"@happyvertical/smrt-approvals:ApprovalEventCollection":{"name":"approvaleventcollection","className":"ApprovalEventCollection","qualifiedName":"@happyvertical/smrt-approvals:ApprovalEventCollection","collection":"approvalevents","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/collections/ApprovalEventCollection.ts","packageName":"@happyvertical/smrt-approvals","fields":{},"methods":{},"decoratorConfig":{"api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"tableName":"approval_events"},"extends":"SmrtCollection","extendsTypeArg":"ApprovalEvent","exportName":"ApprovalEventCollection","collectionExportName":"ApprovalEventCollectionCollection","schema":{"tableName":"approval_events","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_events\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"request_id\\" UUID NOT NULL,\\n \\"type\\" TEXT NOT NULL,\\n \\"actor_id\\" TEXT NOT NULL,\\n \\"actor_type\\" TEXT,\\n \\"reason\\" TEXT,\\n \\"subject_revision_hash\\" TEXT,\\n \\"sequence\\" INTEGER,\\n \\"vote_key\\" TEXT,\\n \\"occurred_at\\" TIMESTAMP,\\n \\"self_approved\\" BOOLEAN DEFAULT FALSE,\\n \\"self_approval_permission\\" TEXT DEFAULT ''\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"request_id":{"type":"UUID","referenceKind":"foreignKey","notNull":true,"unique":false,"foreignKey":{"table":"approval_requests","column":"id","onDelete":"RESTRICT","onUpdate":"RESTRICT","engines":["postgres","sqlite"]}},"type":{"type":"TEXT","notNull":true,"unique":false},"actor_id":{"type":"TEXT","notNull":true,"unique":false},"actor_type":{"type":"TEXT","notNull":false,"unique":false},"reason":{"type":"TEXT","notNull":false,"unique":false},"subject_revision_hash":{"type":"TEXT","notNull":false,"unique":false},"sequence":{"type":"INTEGER","notNull":false,"unique":false},"vote_key":{"type":"TEXT","notNull":false,"unique":false},"occurred_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"self_approved":{"type":"BOOLEAN","notNull":false,"unique":false,"default":false},"self_approval_permission":{"type":"TEXT","notNull":false,"unique":false,"default":""}},"indexes":[{"name":"approval_events_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_events_request_sequence_key","columns":["request_id","sequence"],"unique":true},{"name":"approval_events_request_vote_key","columns":["request_id","vote_key"],"unique":true},{"name":"approval_events_tenant_occurred_idx","columns":["tenant_id","occurred_at"]},{"name":"approval_events_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"998756b0"},"importPath":"@happyvertical/smrt-approvals"},"@happyvertical/smrt-approvals:ApprovalPolicyCollection":{"name":"approvalpolicycollection","className":"ApprovalPolicyCollection","qualifiedName":"@happyvertical/smrt-approvals:ApprovalPolicyCollection","collection":"approvalpolicies","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/collections/ApprovalPolicyCollection.ts","packageName":"@happyvertical/smrt-approvals","fields":{},"methods":{},"decoratorConfig":{"api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"tableName":"approval_policies"},"extends":"SmrtCollection","extendsTypeArg":"ApprovalPolicy","exportName":"ApprovalPolicyCollection","collectionExportName":"ApprovalPolicyCollectionCollection","schema":{"tableName":"approval_policies","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_policies\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"kind\\" TEXT NOT NULL,\\n \\"required_approvals\\" INTEGER,\\n \\"ttl_ms\\" INTEGER,\\n \\"required_permission\\" TEXT,\\n \\"updated_by\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"kind":{"type":"TEXT","notNull":true,"unique":false},"required_approvals":{"type":"INTEGER","notNull":false,"unique":false},"ttl_ms":{"type":"INTEGER","notNull":false,"unique":false},"required_permission":{"type":"TEXT","notNull":false,"unique":false},"updated_by":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"approval_policies_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_policies_tenant_kind_key","columns":["tenant_id","kind"],"unique":true},{"name":"approval_policies_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"80929cc8"},"importPath":"@happyvertical/smrt-approvals"},"@happyvertical/smrt-approvals:ApprovalRequestCollection":{"name":"approvalrequestcollection","className":"ApprovalRequestCollection","qualifiedName":"@happyvertical/smrt-approvals:ApprovalRequestCollection","collection":"approvalrequests","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/collections/ApprovalRequestCollection.ts","packageName":"@happyvertical/smrt-approvals","fields":{},"methods":{},"decoratorConfig":{"api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"tableName":"approval_requests"},"extends":"SmrtCollection","extendsTypeArg":"ApprovalRequest","exportName":"ApprovalRequestCollection","collectionExportName":"ApprovalRequestCollectionCollection","schema":{"tableName":"approval_requests","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_requests\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"kind\\" TEXT NOT NULL,\\n \\"subject_type\\" TEXT NOT NULL,\\n \\"subject_id\\" TEXT NOT NULL,\\n \\"subject_revision_hash\\" TEXT NOT NULL,\\n \\"request_key\\" TEXT NOT NULL,\\n \\"requested_by\\" TEXT NOT NULL,\\n \\"requested_by_type\\" TEXT,\\n \\"summary\\" TEXT,\\n \\"status\\" TEXT,\\n \\"required_approvals\\" INTEGER,\\n \\"approval_count\\" INTEGER,\\n \\"required_permissions\\" TEXT,\\n \\"version\\" INTEGER,\\n \\"expires_at\\" TIMESTAMP,\\n \\"decided_at\\" TIMESTAMP,\\n \\"consumed_at\\" TIMESTAMP,\\n \\"consumed_by\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"kind":{"type":"TEXT","notNull":true,"unique":false},"subject_type":{"type":"TEXT","notNull":true,"unique":false},"subject_id":{"type":"TEXT","notNull":true,"unique":false},"subject_revision_hash":{"type":"TEXT","notNull":true,"unique":false},"request_key":{"type":"TEXT","notNull":true,"unique":false},"requested_by":{"type":"TEXT","notNull":true,"unique":false},"requested_by_type":{"type":"TEXT","notNull":false,"unique":false},"summary":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":false,"unique":false},"required_approvals":{"type":"INTEGER","notNull":false,"unique":false},"approval_count":{"type":"INTEGER","notNull":false,"unique":false},"required_permissions":{"type":"TEXT","notNull":false,"unique":false},"version":{"type":"INTEGER","notNull":false,"unique":false},"expires_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"decided_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"consumed_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"consumed_by":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"approval_requests_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_requests_tenant_request_key","columns":["tenant_id","request_key"],"unique":true},{"name":"approval_requests_status_expiry_idx","columns":["tenant_id","status","expires_at"]},{"name":"approval_requests_subject_idx","columns":["tenant_id","subject_type","subject_id"]},{"name":"approval_requests_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"a5800bdd"},"importPath":"@happyvertical/smrt-approvals"},"@happyvertical/smrt-approvals:ApprovalEvent":{"name":"approvalevent","className":"ApprovalEvent","qualifiedName":"@happyvertical/smrt-approvals:ApprovalEvent","collection":"approvalevents","description":"One immutable entry in an approval request's history.","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/models/ApprovalEvent.ts","packageName":"@happyvertical/smrt-approvals","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"requestId":{"type":"foreignKey","required":true,"related":"ApprovalRequest","_meta":{"required":true,"constraint":{"engines":["postgres","sqlite"]},"onDelete":"RESTRICT","onUpdate":"RESTRICT"}},"type":{"type":"text","required":true,"_meta":{"required":true,"readonly":true},"readonly":true},"actorId":{"type":"text","required":true,"_meta":{"required":true,"readonly":true},"readonly":true},"actorType":{"type":"text","required":false,"_meta":{"readonly":true},"enum":["human","agent","service"],"readonly":true},"reason":{"type":"text","required":false,"_meta":{"readonly":true},"readonly":true},"subjectRevisionHash":{"type":"text","required":false,"_meta":{"readonly":true},"readonly":true},"sequence":{"type":"integer","required":false,"_meta":{"readonly":true},"readonly":true},"voteKey":{"type":"text","required":false,"_meta":{"nullable":true,"readonly":true},"readonly":true},"occurredAt":{"type":"datetime","required":false,"_meta":{"readonly":true},"readonly":true},"selfApproved":{"type":"boolean","required":false,"default":false,"_meta":{"readonly":true,"default":false},"readonly":true},"selfApprovalPermission":{"type":"text","required":false,"default":"","_meta":{"readonly":true,"default":""},"readonly":true}},"methods":{"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"delete":{"name":"delete","async":true,"parameters":[],"returnType":"Promise<void>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"approval_events","api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"indexes":[{"name":"approval_events_request_sequence_key","columns":["requestId","sequence"],"unique":true},{"name":"approval_events_request_vote_key","columns":["requestId","voteKey"],"unique":true},{"name":"approval_events_tenant_occurred_idx","columns":["tenantId","occurredAt"]}],"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"ApprovalEvent","collectionExportName":"ApprovalEventCollection","validationRules":[{"field":"requestId","rule":"required","fieldType":"foreignKey"},{"field":"type","rule":"required","fieldType":"text"},{"field":"actorId","rule":"required","fieldType":"text"}],"schema":{"tableName":"approval_events","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_events\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"request_id\\" UUID NOT NULL,\\n \\"type\\" TEXT NOT NULL,\\n \\"actor_id\\" TEXT NOT NULL,\\n \\"actor_type\\" TEXT,\\n \\"reason\\" TEXT,\\n \\"subject_revision_hash\\" TEXT,\\n \\"sequence\\" INTEGER,\\n \\"vote_key\\" TEXT,\\n \\"occurred_at\\" TIMESTAMP,\\n \\"self_approved\\" BOOLEAN DEFAULT FALSE,\\n \\"self_approval_permission\\" TEXT DEFAULT ''\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"request_id":{"type":"UUID","referenceKind":"foreignKey","notNull":true,"unique":false,"foreignKey":{"table":"approval_requests","column":"id","onDelete":"RESTRICT","onUpdate":"RESTRICT","engines":["postgres","sqlite"]}},"type":{"type":"TEXT","notNull":true,"unique":false},"actor_id":{"type":"TEXT","notNull":true,"unique":false},"actor_type":{"type":"TEXT","notNull":false,"unique":false},"reason":{"type":"TEXT","notNull":false,"unique":false},"subject_revision_hash":{"type":"TEXT","notNull":false,"unique":false},"sequence":{"type":"INTEGER","notNull":false,"unique":false},"vote_key":{"type":"TEXT","notNull":false,"unique":false},"occurred_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"self_approved":{"type":"BOOLEAN","notNull":false,"unique":false,"default":false},"self_approval_permission":{"type":"TEXT","notNull":false,"unique":false,"default":""}},"indexes":[{"name":"approval_events_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_events_request_sequence_key","columns":["request_id","sequence"],"unique":true},{"name":"approval_events_request_vote_key","columns":["request_id","vote_key"],"unique":true},{"name":"approval_events_tenant_occurred_idx","columns":["tenant_id","occurred_at"]},{"name":"approval_events_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"998756b0"},"importPath":"@happyvertical/smrt-approvals"},"@happyvertical/smrt-approvals:ApprovalPolicy":{"name":"approvalpolicy","className":"ApprovalPolicy","qualifiedName":"@happyvertical/smrt-approvals:ApprovalPolicy","collection":"approvalpolicies","description":"Tenant-level tightening of an approval kind. One row per tenant and kind.","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/models/ApprovalPolicy.ts","packageName":"@happyvertical/smrt-approvals","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"kind":{"type":"text","required":true,"_meta":{"required":true}},"requiredApprovals":{"type":"integer","required":false,"_meta":{}},"ttlMs":{"type":"integer","required":false,"_meta":{}},"requiredPermission":{"type":"text","required":false,"_meta":{}},"updatedBy":{"type":"text","required":false,"_meta":{}}},"methods":{"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"approval_policies","api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"indexes":[{"name":"approval_policies_tenant_kind_key","columns":["tenantId","kind"],"unique":true}],"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"ApprovalPolicy","collectionExportName":"ApprovalPolicyCollection","validationRules":[{"field":"kind","rule":"required","fieldType":"text"}],"schema":{"tableName":"approval_policies","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_policies\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"kind\\" TEXT NOT NULL,\\n \\"required_approvals\\" INTEGER,\\n \\"ttl_ms\\" INTEGER,\\n \\"required_permission\\" TEXT,\\n \\"updated_by\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"kind":{"type":"TEXT","notNull":true,"unique":false},"required_approvals":{"type":"INTEGER","notNull":false,"unique":false},"ttl_ms":{"type":"INTEGER","notNull":false,"unique":false},"required_permission":{"type":"TEXT","notNull":false,"unique":false},"updated_by":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"approval_policies_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_policies_tenant_kind_key","columns":["tenant_id","kind"],"unique":true},{"name":"approval_policies_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"80929cc8"},"importPath":"@happyvertical/smrt-approvals"},"@happyvertical/smrt-approvals:ApprovalRequest":{"name":"approvalrequest","className":"ApprovalRequest","qualifiedName":"@happyvertical/smrt-approvals:ApprovalRequest","collection":"approvalrequests","description":"A request for approval of one subject revision.","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/models/ApprovalRequest.ts","packageName":"@happyvertical/smrt-approvals","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"kind":{"type":"text","required":true,"_meta":{"required":true,"readonly":true},"readonly":true},"subjectType":{"type":"text","required":true,"_meta":{"required":true,"readonly":true},"readonly":true},"subjectId":{"type":"text","required":true,"_meta":{"required":true,"readonly":true},"readonly":true},"subjectRevisionHash":{"type":"text","required":true,"_meta":{"required":true,"readonly":true},"readonly":true},"requestKey":{"type":"text","required":true,"_meta":{"required":true,"readonly":true},"readonly":true},"requestedBy":{"type":"text","required":true,"_meta":{"required":true,"readonly":true},"readonly":true},"requestedByType":{"type":"text","required":false,"_meta":{"readonly":true},"enum":["human","agent","service"],"readonly":true},"summary":{"type":"text","required":false,"_meta":{"readonly":true},"readonly":true},"status":{"type":"text","required":false,"_meta":{"readonly":true},"readonly":true},"requiredApprovals":{"type":"integer","required":false,"_meta":{"readonly":true},"readonly":true},"approvalCount":{"type":"integer","required":false,"_meta":{"readonly":true},"readonly":true},"requiredPermissions":{"type":"text","required":false,"_meta":{"readonly":true},"readonly":true},"version":{"type":"integer","required":false,"_meta":{"readonly":true},"readonly":true},"expiresAt":{"type":"datetime","required":false,"_meta":{"readonly":true},"readonly":true},"decidedAt":{"type":"datetime","required":false,"_meta":{"readonly":true},"readonly":true},"consumedAt":{"type":"datetime","required":false,"_meta":{"readonly":true},"readonly":true},"consumedBy":{"type":"text","required":false,"_meta":{"readonly":true},"readonly":true}},"methods":{"getRequiredPermissions":{"name":"getRequiredPermissions","async":false,"parameters":[],"returnType":"string[]","isStatic":false,"isPublic":true},"setRequiredPermissions":{"name":"setRequiredPermissions","async":false,"parameters":[{"name":"slugs","type":"any","optional":false,"typeUnresolved":true}],"returnType":"void","isStatic":false,"isPublic":true},"expiresAtMs":{"name":"expiresAtMs","async":false,"parameters":[],"returnType":"number","isStatic":false,"isPublic":true},"isConsumed":{"name":"isConsumed","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"delete":{"name":"delete","async":true,"parameters":[],"returnType":"Promise<void>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"approval_requests","api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"indexes":[{"name":"approval_requests_tenant_request_key","columns":["tenantId","requestKey"],"unique":true},{"name":"approval_requests_status_expiry_idx","columns":["tenantId","status","expiresAt"]},{"name":"approval_requests_subject_idx","columns":["tenantId","subjectType","subjectId"]}],"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"ApprovalRequest","collectionExportName":"ApprovalRequestCollection","validationRules":[{"field":"kind","rule":"required","fieldType":"text"},{"field":"subjectType","rule":"required","fieldType":"text"},{"field":"subjectId","rule":"required","fieldType":"text"},{"field":"subjectRevisionHash","rule":"required","fieldType":"text"},{"field":"requestKey","rule":"required","fieldType":"text"},{"field":"requestedBy","rule":"required","fieldType":"text"}],"schema":{"tableName":"approval_requests","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_requests\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"kind\\" TEXT NOT NULL,\\n \\"subject_type\\" TEXT NOT NULL,\\n \\"subject_id\\" TEXT NOT NULL,\\n \\"subject_revision_hash\\" TEXT NOT NULL,\\n \\"request_key\\" TEXT NOT NULL,\\n \\"requested_by\\" TEXT NOT NULL,\\n \\"requested_by_type\\" TEXT,\\n \\"summary\\" TEXT,\\n \\"status\\" TEXT,\\n \\"required_approvals\\" INTEGER,\\n \\"approval_count\\" INTEGER,\\n \\"required_permissions\\" TEXT,\\n \\"version\\" INTEGER,\\n \\"expires_at\\" TIMESTAMP,\\n \\"decided_at\\" TIMESTAMP,\\n \\"consumed_at\\" TIMESTAMP,\\n \\"consumed_by\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"kind":{"type":"TEXT","notNull":true,"unique":false},"subject_type":{"type":"TEXT","notNull":true,"unique":false},"subject_id":{"type":"TEXT","notNull":true,"unique":false},"subject_revision_hash":{"type":"TEXT","notNull":true,"unique":false},"request_key":{"type":"TEXT","notNull":true,"unique":false},"requested_by":{"type":"TEXT","notNull":true,"unique":false},"requested_by_type":{"type":"TEXT","notNull":false,"unique":false},"summary":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":false,"unique":false},"required_approvals":{"type":"INTEGER","notNull":false,"unique":false},"approval_count":{"type":"INTEGER","notNull":false,"unique":false},"required_permissions":{"type":"TEXT","notNull":false,"unique":false},"version":{"type":"INTEGER","notNull":false,"unique":false},"expires_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"decided_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"consumed_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"consumed_by":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"approval_requests_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_requests_tenant_request_key","columns":["tenant_id","request_key"],"unique":true},{"name":"approval_requests_status_expiry_idx","columns":["tenant_id","status","expires_at"]},{"name":"approval_requests_subject_idx","columns":["tenant_id","subject_type","subject_id"]},{"name":"approval_requests_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"a5800bdd"},"importPath":"@happyvertical/smrt-approvals"}},"moduleType":"smrt","smrtDependencies":["@happyvertical/smrt-core","@happyvertical/smrt-tenancy","@happyvertical/smrt-users"],"browser":{"status":"server-only","issues":["#3617","#3624","#3626"],"via":["@happyvertical/smrt-profiles","@happyvertical/smrt-tenancy","@happyvertical/smrt-users"]},"stampsConstructors":true}`));
6
+ ObjectRegistry.registerPackageManifest(JSON.parse(`{"version":"1.0.0","timestamp":0,"packageName":"@happyvertical/smrt-approvals","packageVersion":"0.57.38","objects":{"@happyvertical/smrt-approvals:ApprovalEventCollection":{"name":"approvaleventcollection","className":"ApprovalEventCollection","qualifiedName":"@happyvertical/smrt-approvals:ApprovalEventCollection","collection":"approvalevents","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/collections/ApprovalEventCollection.ts","packageName":"@happyvertical/smrt-approvals","fields":{},"methods":{},"decoratorConfig":{"api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"tableName":"approval_events"},"extends":"SmrtCollection","extendsTypeArg":"ApprovalEvent","exportName":"ApprovalEventCollection","collectionExportName":"ApprovalEventCollectionCollection","schema":{"tableName":"approval_events","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_events\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"request_id\\" UUID NOT NULL,\\n \\"type\\" TEXT NOT NULL,\\n \\"actor_id\\" TEXT NOT NULL,\\n \\"actor_type\\" TEXT,\\n \\"reason\\" TEXT,\\n \\"subject_revision_hash\\" TEXT,\\n \\"sequence\\" INTEGER,\\n \\"vote_key\\" TEXT,\\n \\"occurred_at\\" TIMESTAMP,\\n \\"self_approved\\" BOOLEAN DEFAULT FALSE,\\n \\"self_approval_permission\\" TEXT DEFAULT ''\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"request_id":{"type":"UUID","referenceKind":"foreignKey","notNull":true,"unique":false,"foreignKey":{"table":"approval_requests","column":"id","onDelete":"RESTRICT","onUpdate":"RESTRICT","engines":["postgres","sqlite"]}},"type":{"type":"TEXT","notNull":true,"unique":false},"actor_id":{"type":"TEXT","notNull":true,"unique":false},"actor_type":{"type":"TEXT","notNull":false,"unique":false},"reason":{"type":"TEXT","notNull":false,"unique":false},"subject_revision_hash":{"type":"TEXT","notNull":false,"unique":false},"sequence":{"type":"INTEGER","notNull":false,"unique":false},"vote_key":{"type":"TEXT","notNull":false,"unique":false},"occurred_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"self_approved":{"type":"BOOLEAN","notNull":false,"unique":false,"default":false},"self_approval_permission":{"type":"TEXT","notNull":false,"unique":false,"default":""}},"indexes":[{"name":"approval_events_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_events_request_sequence_key","columns":["request_id","sequence"],"unique":true},{"name":"approval_events_request_vote_key","columns":["request_id","vote_key"],"unique":true},{"name":"approval_events_tenant_occurred_idx","columns":["tenant_id","occurred_at"]},{"name":"approval_events_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"998756b0"},"importPath":"@happyvertical/smrt-approvals"},"@happyvertical/smrt-approvals:ApprovalPolicyCollection":{"name":"approvalpolicycollection","className":"ApprovalPolicyCollection","qualifiedName":"@happyvertical/smrt-approvals:ApprovalPolicyCollection","collection":"approvalpolicies","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/collections/ApprovalPolicyCollection.ts","packageName":"@happyvertical/smrt-approvals","fields":{},"methods":{},"decoratorConfig":{"api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"tableName":"approval_policies"},"extends":"SmrtCollection","extendsTypeArg":"ApprovalPolicy","exportName":"ApprovalPolicyCollection","collectionExportName":"ApprovalPolicyCollectionCollection","schema":{"tableName":"approval_policies","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_policies\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"kind\\" TEXT NOT NULL,\\n \\"required_approvals\\" INTEGER,\\n \\"ttl_ms\\" INTEGER,\\n \\"required_permission\\" TEXT,\\n \\"updated_by\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"kind":{"type":"TEXT","notNull":true,"unique":false},"required_approvals":{"type":"INTEGER","notNull":false,"unique":false},"ttl_ms":{"type":"INTEGER","notNull":false,"unique":false},"required_permission":{"type":"TEXT","notNull":false,"unique":false},"updated_by":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"approval_policies_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_policies_tenant_kind_key","columns":["tenant_id","kind"],"unique":true},{"name":"approval_policies_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"80929cc8"},"importPath":"@happyvertical/smrt-approvals"},"@happyvertical/smrt-approvals:ApprovalRequestCollection":{"name":"approvalrequestcollection","className":"ApprovalRequestCollection","qualifiedName":"@happyvertical/smrt-approvals:ApprovalRequestCollection","collection":"approvalrequests","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/collections/ApprovalRequestCollection.ts","packageName":"@happyvertical/smrt-approvals","fields":{},"methods":{},"decoratorConfig":{"api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"tableName":"approval_requests"},"extends":"SmrtCollection","extendsTypeArg":"ApprovalRequest","exportName":"ApprovalRequestCollection","collectionExportName":"ApprovalRequestCollectionCollection","schema":{"tableName":"approval_requests","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_requests\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"kind\\" TEXT NOT NULL,\\n \\"subject_type\\" TEXT NOT NULL,\\n \\"subject_id\\" TEXT NOT NULL,\\n \\"subject_revision_hash\\" TEXT NOT NULL,\\n \\"request_key\\" TEXT NOT NULL,\\n \\"requested_by\\" TEXT NOT NULL,\\n \\"requested_by_type\\" TEXT,\\n \\"summary\\" TEXT,\\n \\"status\\" TEXT,\\n \\"required_approvals\\" INTEGER,\\n \\"approval_count\\" INTEGER,\\n \\"required_permissions\\" TEXT,\\n \\"version\\" INTEGER,\\n \\"expires_at\\" TIMESTAMP,\\n \\"decided_at\\" TIMESTAMP,\\n \\"consumed_at\\" TIMESTAMP,\\n \\"consumed_by\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"kind":{"type":"TEXT","notNull":true,"unique":false},"subject_type":{"type":"TEXT","notNull":true,"unique":false},"subject_id":{"type":"TEXT","notNull":true,"unique":false},"subject_revision_hash":{"type":"TEXT","notNull":true,"unique":false},"request_key":{"type":"TEXT","notNull":true,"unique":false},"requested_by":{"type":"TEXT","notNull":true,"unique":false},"requested_by_type":{"type":"TEXT","notNull":false,"unique":false},"summary":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":false,"unique":false},"required_approvals":{"type":"INTEGER","notNull":false,"unique":false},"approval_count":{"type":"INTEGER","notNull":false,"unique":false},"required_permissions":{"type":"TEXT","notNull":false,"unique":false},"version":{"type":"INTEGER","notNull":false,"unique":false},"expires_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"decided_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"consumed_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"consumed_by":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"approval_requests_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_requests_tenant_request_key","columns":["tenant_id","request_key"],"unique":true},{"name":"approval_requests_status_expiry_idx","columns":["tenant_id","status","expires_at"]},{"name":"approval_requests_subject_idx","columns":["tenant_id","subject_type","subject_id"]},{"name":"approval_requests_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"a5800bdd"},"importPath":"@happyvertical/smrt-approvals"},"@happyvertical/smrt-approvals:ApprovalEvent":{"name":"approvalevent","className":"ApprovalEvent","qualifiedName":"@happyvertical/smrt-approvals:ApprovalEvent","collection":"approvalevents","description":"One immutable entry in an approval request's history.","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/models/ApprovalEvent.ts","packageName":"@happyvertical/smrt-approvals","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"requestId":{"type":"foreignKey","required":true,"related":"ApprovalRequest","description":"The request this entry belongs to.","_meta":{"description":"The request this entry belongs to.","required":true,"constraint":{"engines":["postgres","sqlite"]},"onDelete":"RESTRICT","onUpdate":"RESTRICT"}},"type":{"type":"text","required":true,"description":"What happened: created, approved, rejected, changes requested, cancelled, expired or used.","_meta":{"required":true,"readonly":true,"description":"What happened: created, approved, rejected, changes requested, cancelled, expired or used."},"readonly":true},"actorId":{"type":"text","required":true,"description":"Who did it.","_meta":{"required":true,"readonly":true,"description":"Who did it."},"readonly":true},"actorType":{"type":"text","required":false,"description":"Whether a person, an assistant or an automated process did it.","_meta":{"readonly":true,"description":"Whether a person, an assistant or an automated process did it."},"enum":["human","agent","service"],"readonly":true},"reason":{"type":"text","required":false,"description":"The reason given, for example why a request was rejected or cancelled.","_meta":{"readonly":true,"description":"The reason given, for example why a request was rejected or cancelled."},"readonly":true},"subjectRevisionHash":{"type":"text","required":false,"_meta":{"readonly":true},"readonly":true},"sequence":{"type":"integer","required":false,"_meta":{"readonly":true},"readonly":true},"voteKey":{"type":"text","required":false,"_meta":{"nullable":true,"readonly":true},"readonly":true},"occurredAt":{"type":"datetime","required":false,"description":"When it happened.","_meta":{"readonly":true,"description":"When it happened."},"readonly":true},"selfApproved":{"type":"boolean","required":false,"default":false,"description":"Whether the person who asked also decided, where that is allowed.","_meta":{"readonly":true,"default":false,"description":"Whether the person who asked also decided, where that is allowed."},"readonly":true},"selfApprovalPermission":{"type":"text","required":false,"default":"","_meta":{"readonly":true,"default":""},"readonly":true}},"methods":{"save":{"name":"save","async":true,"parameters":[{"name":"options","type":"SmrtSaveOptions","optional":true}],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"delete":{"name":"delete","async":true,"parameters":[],"returnType":"Promise<void>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"approval_events","api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"indexes":[{"name":"approval_events_request_sequence_key","columns":["requestId","sequence"],"unique":true},{"name":"approval_events_request_vote_key","columns":["requestId","voteKey"],"unique":true},{"name":"approval_events_tenant_occurred_idx","columns":["tenantId","occurredAt"]}],"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"ApprovalEvent","collectionExportName":"ApprovalEventCollection","validationRules":[{"field":"requestId","rule":"required","fieldType":"foreignKey"},{"field":"type","rule":"required","fieldType":"text"},{"field":"actorId","rule":"required","fieldType":"text"}],"schema":{"tableName":"approval_events","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_events\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"request_id\\" UUID NOT NULL,\\n \\"type\\" TEXT NOT NULL,\\n \\"actor_id\\" TEXT NOT NULL,\\n \\"actor_type\\" TEXT,\\n \\"reason\\" TEXT,\\n \\"subject_revision_hash\\" TEXT,\\n \\"sequence\\" INTEGER,\\n \\"vote_key\\" TEXT,\\n \\"occurred_at\\" TIMESTAMP,\\n \\"self_approved\\" BOOLEAN DEFAULT FALSE,\\n \\"self_approval_permission\\" TEXT DEFAULT ''\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"request_id":{"type":"UUID","referenceKind":"foreignKey","notNull":true,"unique":false,"foreignKey":{"table":"approval_requests","column":"id","onDelete":"RESTRICT","onUpdate":"RESTRICT","engines":["postgres","sqlite"]}},"type":{"type":"TEXT","notNull":true,"unique":false},"actor_id":{"type":"TEXT","notNull":true,"unique":false},"actor_type":{"type":"TEXT","notNull":false,"unique":false},"reason":{"type":"TEXT","notNull":false,"unique":false},"subject_revision_hash":{"type":"TEXT","notNull":false,"unique":false},"sequence":{"type":"INTEGER","notNull":false,"unique":false},"vote_key":{"type":"TEXT","notNull":false,"unique":false},"occurred_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"self_approved":{"type":"BOOLEAN","notNull":false,"unique":false,"default":false},"self_approval_permission":{"type":"TEXT","notNull":false,"unique":false,"default":""}},"indexes":[{"name":"approval_events_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_events_request_sequence_key","columns":["request_id","sequence"],"unique":true},{"name":"approval_events_request_vote_key","columns":["request_id","vote_key"],"unique":true},{"name":"approval_events_tenant_occurred_idx","columns":["tenant_id","occurred_at"]},{"name":"approval_events_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"998756b0"},"importPath":"@happyvertical/smrt-approvals"},"@happyvertical/smrt-approvals:ApprovalPolicy":{"name":"approvalpolicy","className":"ApprovalPolicy","qualifiedName":"@happyvertical/smrt-approvals:ApprovalPolicy","collection":"approvalpolicies","description":"Tenant-level tightening of an approval kind. One row per tenant and kind.","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/models/ApprovalPolicy.ts","packageName":"@happyvertical/smrt-approvals","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"kind":{"type":"text","required":true,"description":"The sort of approval these rules apply to.","_meta":{"required":true,"description":"The sort of approval these rules apply to."}},"requiredApprovals":{"type":"integer","required":false,"description":"How many different people must agree. Zero keeps the usual number.","_meta":{"description":"How many different people must agree. Zero keeps the usual number."}},"ttlMs":{"type":"integer","required":false,"description":"How long a request stays open, in milliseconds. Zero keeps the usual time.","_meta":{"description":"How long a request stays open, in milliseconds. Zero keeps the usual time."}},"requiredPermission":{"type":"text","required":false,"description":"An extra permission a decider must hold. Leave empty for none.","_meta":{"description":"An extra permission a decider must hold. Leave empty for none."}},"updatedBy":{"type":"text","required":false,"description":"Who last changed these rules.","_meta":{"description":"Who last changed these rules."}}},"methods":{"save":{"name":"save","async":true,"parameters":[{"name":"options","type":"SmrtSaveOptions","optional":true}],"returnType":"Promise<this>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"approval_policies","api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"indexes":[{"name":"approval_policies_tenant_kind_key","columns":["tenantId","kind"],"unique":true}],"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"ApprovalPolicy","collectionExportName":"ApprovalPolicyCollection","validationRules":[{"field":"kind","rule":"required","fieldType":"text"}],"schema":{"tableName":"approval_policies","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_policies\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"kind\\" TEXT NOT NULL,\\n \\"required_approvals\\" INTEGER,\\n \\"ttl_ms\\" INTEGER,\\n \\"required_permission\\" TEXT,\\n \\"updated_by\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"kind":{"type":"TEXT","notNull":true,"unique":false},"required_approvals":{"type":"INTEGER","notNull":false,"unique":false},"ttl_ms":{"type":"INTEGER","notNull":false,"unique":false},"required_permission":{"type":"TEXT","notNull":false,"unique":false},"updated_by":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"approval_policies_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_policies_tenant_kind_key","columns":["tenant_id","kind"],"unique":true},{"name":"approval_policies_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"80929cc8"},"importPath":"@happyvertical/smrt-approvals"},"@happyvertical/smrt-approvals:ApprovalRequest":{"name":"approvalrequest","className":"ApprovalRequest","qualifiedName":"@happyvertical/smrt-approvals:ApprovalRequest","collection":"approvalrequests","description":"A request for approval of one subject revision.","filePath":"/home/runner/work/smrt/smrt/packages/approvals/src/models/ApprovalRequest.ts","packageName":"@happyvertical/smrt-approvals","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"kind":{"type":"text","required":true,"description":"What sort of approval this is, such as publishing a post.","_meta":{"required":true,"readonly":true,"description":"What sort of approval this is, such as publishing a post."},"readonly":true},"subjectType":{"type":"text","required":true,"description":"What kind of thing the request is about.","_meta":{"required":true,"readonly":true,"description":"What kind of thing the request is about."},"readonly":true},"subjectId":{"type":"text","required":true,"description":"Which thing the request is about.","_meta":{"required":true,"readonly":true,"description":"Which thing the request is about."},"readonly":true},"subjectRevisionHash":{"type":"text","required":true,"description":"A fingerprint of the exact version that was put up for approval. If the thing changes, the approval no longer applies.","_meta":{"required":true,"readonly":true,"description":"A fingerprint of the exact version that was put up for approval. If the thing changes, the approval no longer applies."},"readonly":true},"requestKey":{"type":"text","required":true,"description":"The reference the request is filed under, so asking twice does not open it twice.","_meta":{"required":true,"readonly":true,"description":"The reference the request is filed under, so asking twice does not open it twice."},"readonly":true},"requestedBy":{"type":"text","required":true,"description":"Who asked for the approval.","_meta":{"required":true,"readonly":true,"description":"Who asked for the approval."},"readonly":true},"requestedByType":{"type":"text","required":false,"description":"Whether a person, an assistant or an automated process asked.","_meta":{"readonly":true,"description":"Whether a person, an assistant or an automated process asked."},"enum":["human","agent","service"],"readonly":true},"summary":{"type":"text","required":false,"description":"A short description of what needs approval.","_meta":{"readonly":true,"description":"A short description of what needs approval."},"readonly":true},"status":{"type":"text","required":false,"description":"Where the request stands: waiting, approved, rejected, changes requested, cancelled or expired.","_meta":{"readonly":true,"description":"Where the request stands: waiting, approved, rejected, changes requested, cancelled or expired."},"readonly":true},"requiredApprovals":{"type":"integer","required":false,"description":"How many different people must agree.","_meta":{"readonly":true,"description":"How many different people must agree."},"readonly":true},"approvalCount":{"type":"integer","required":false,"description":"How many people have agreed so far.","_meta":{"readonly":true,"description":"How many people have agreed so far."},"readonly":true},"requiredPermissions":{"type":"text","required":false,"_meta":{"readonly":true},"readonly":true},"version":{"type":"integer","required":false,"_meta":{"readonly":true},"readonly":true},"expiresAt":{"type":"datetime","required":false,"description":"The deadline. After it the request can no longer be decided.","_meta":{"readonly":true,"description":"The deadline. After it the request can no longer be decided."},"readonly":true},"decidedAt":{"type":"datetime","required":false,"description":"When the request was decided.","_meta":{"readonly":true,"description":"When the request was decided."},"readonly":true},"consumedAt":{"type":"datetime","required":false,"description":"When the approval was used to let the action go ahead.","_meta":{"readonly":true,"description":"When the approval was used to let the action go ahead."},"readonly":true},"consumedBy":{"type":"text","required":false,"description":"Who used the approval.","_meta":{"readonly":true,"description":"Who used the approval."},"readonly":true}},"methods":{"getRequiredPermissions":{"name":"getRequiredPermissions","async":false,"parameters":[],"returnType":"string[]","isStatic":false,"isPublic":true},"setRequiredPermissions":{"name":"setRequiredPermissions","async":false,"parameters":[{"name":"slugs","type":"any","optional":false,"typeUnresolved":true}],"returnType":"void","isStatic":false,"isPublic":true},"expiresAtMs":{"name":"expiresAtMs","async":false,"parameters":[],"returnType":"number","isStatic":false,"isPublic":true},"isConsumed":{"name":"isConsumed","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"save":{"name":"save","async":true,"parameters":[{"name":"options","type":"SmrtSaveOptions","optional":true}],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"delete":{"name":"delete","async":true,"parameters":[],"returnType":"Promise<void>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"approval_requests","api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":false,"indexes":[{"name":"approval_requests_tenant_request_key","columns":["tenantId","requestKey"],"unique":true},{"name":"approval_requests_status_expiry_idx","columns":["tenantId","status","expiresAt"]},{"name":"approval_requests_subject_idx","columns":["tenantId","subjectType","subjectId"]}],"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"ApprovalRequest","collectionExportName":"ApprovalRequestCollection","validationRules":[{"field":"kind","rule":"required","fieldType":"text"},{"field":"subjectType","rule":"required","fieldType":"text"},{"field":"subjectId","rule":"required","fieldType":"text"},{"field":"subjectRevisionHash","rule":"required","fieldType":"text"},{"field":"requestKey","rule":"required","fieldType":"text"},{"field":"requestedBy","rule":"required","fieldType":"text"}],"schema":{"tableName":"approval_requests","ddl":"CREATE TABLE IF NOT EXISTS \\"approval_requests\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"kind\\" TEXT NOT NULL,\\n \\"subject_type\\" TEXT NOT NULL,\\n \\"subject_id\\" TEXT NOT NULL,\\n \\"subject_revision_hash\\" TEXT NOT NULL,\\n \\"request_key\\" TEXT NOT NULL,\\n \\"requested_by\\" TEXT NOT NULL,\\n \\"requested_by_type\\" TEXT,\\n \\"summary\\" TEXT,\\n \\"status\\" TEXT,\\n \\"required_approvals\\" INTEGER,\\n \\"approval_count\\" INTEGER,\\n \\"required_permissions\\" TEXT,\\n \\"version\\" INTEGER,\\n \\"expires_at\\" TIMESTAMP,\\n \\"decided_at\\" TIMESTAMP,\\n \\"consumed_at\\" TIMESTAMP,\\n \\"consumed_by\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"kind":{"type":"TEXT","notNull":true,"unique":false},"subject_type":{"type":"TEXT","notNull":true,"unique":false},"subject_id":{"type":"TEXT","notNull":true,"unique":false},"subject_revision_hash":{"type":"TEXT","notNull":true,"unique":false},"request_key":{"type":"TEXT","notNull":true,"unique":false},"requested_by":{"type":"TEXT","notNull":true,"unique":false},"requested_by_type":{"type":"TEXT","notNull":false,"unique":false},"summary":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":false,"unique":false},"required_approvals":{"type":"INTEGER","notNull":false,"unique":false},"approval_count":{"type":"INTEGER","notNull":false,"unique":false},"required_permissions":{"type":"TEXT","notNull":false,"unique":false},"version":{"type":"INTEGER","notNull":false,"unique":false},"expires_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"decided_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"consumed_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"consumed_by":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"approval_requests_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"approval_requests_tenant_request_key","columns":["tenant_id","request_key"],"unique":true},{"name":"approval_requests_status_expiry_idx","columns":["tenant_id","status","expires_at"]},{"name":"approval_requests_subject_idx","columns":["tenant_id","subject_type","subject_id"]},{"name":"approval_requests_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"a5800bdd"},"importPath":"@happyvertical/smrt-approvals"}},"moduleType":"smrt","recipes":[{"id":"approvals.requests","className":"ApprovalsRecipe","label":"Approvals","summary":"See what is waiting for a yes, who decided what, and the rules each kind of approval follows.","synonyms":["approvals","approval requests","sign-off","sign off","authorisation","authorization","review queue","waiting for approval"],"models":["@happyvertical/smrt-approvals:ApprovalRequest","@happyvertical/smrt-approvals:ApprovalEvent","@happyvertical/smrt-approvals:ApprovalPolicy"],"nav":[{"label":"Requests","model":"@happyvertical/smrt-approvals:ApprovalRequest","icon":"fileText","description":"Everything waiting for a yes or already decided, and where each one stands.","noun":"request"},{"label":"History","model":"@happyvertical/smrt-approvals:ApprovalEvent","icon":"book","description":"Who did what on each request, and when.","noun":"history entry"},{"label":"Policies","model":"@happyvertical/smrt-approvals:ApprovalPolicy","icon":"settings","description":"The rules for each kind of approval: how many people must agree and how long a request lasts.","noun":"policy"}],"requires":[],"section":{"id":"approvals","label":"Approvals","icon":"briefcase","description":"Who has to say yes before something happens."},"options":{"@happyvertical/smrt-approvals:ApprovalRequest":{"fields":{"summary":{"order":1},"kind":{"order":2},"status":{"order":3},"requestedBy":{"label":"Requested by","order":4},"requestedByType":{"label":"Requested by a","order":5},"expiresAt":{"label":"Expires","order":6},"decidedAt":{"label":"Decided on","order":7},"subjectType":{"label":"What it is about","visibility":"advanced"},"subjectId":{"label":"Which one","visibility":"advanced"},"requiredApprovals":{"label":"Approvals needed","visibility":"advanced"},"approvalCount":{"label":"Approvals so far","visibility":"advanced"},"consumedAt":{"label":"Used on","visibility":"advanced"},"consumedBy":{"label":"Used by","visibility":"advanced"},"tenantId":{"visibility":"hidden"},"subjectRevisionHash":{"visibility":"hidden"},"requestKey":{"visibility":"hidden"},"requiredPermissions":{"visibility":"hidden"},"version":{"visibility":"hidden"}}},"@happyvertical/smrt-approvals:ApprovalEvent":{"fields":{"requestId":{"label":"Request","order":1},"type":{"label":"What happened","order":2},"actorId":{"label":"Who","order":3},"actorType":{"label":"Who it was","order":4},"reason":{"order":5},"occurredAt":{"label":"When","order":6},"selfApproved":{"label":"Decided by the requester","visibility":"advanced"},"tenantId":{"visibility":"hidden"},"subjectRevisionHash":{"visibility":"hidden"},"sequence":{"visibility":"hidden"},"voteKey":{"visibility":"hidden"},"selfApprovalPermission":{"visibility":"hidden"}}},"@happyvertical/smrt-approvals:ApprovalPolicy":{"fields":{"kind":{"order":1},"requiredApprovals":{"label":"Approvals needed","order":2},"ttlMs":{"label":"Time limit in milliseconds","order":3},"requiredPermission":{"label":"Extra permission needed","order":4},"updatedBy":{"label":"Last changed by","order":5},"tenantId":{"visibility":"hidden"}}}},"help":{"markdown":"## Overview\\n\\nApprovals is where you see who has to say yes before something happens, such\\nas publishing a post or sending an order. Each request names what needs\\napproval, who asked and where it stands: waiting, approved, rejected, changes\\nrequested, cancelled or expired. The history keeps every step taken on a\\nrequest, and the policies show the rules each kind of approval follows.\\n\\n## Tasks\\n\\nRequests are raised by the app or by an assistant through the approval\\nservice, decisions are recorded by the same service, and policies are set by\\nan administrator through it. Nothing here is created or changed by hand in the\\napp. Here you find a request, see where it stands and read what happened.\\n\\n### Find a request\\n\\n1. Open the list of requests.\\n2. Look at the **{field:ApprovalRequest.summary}** to see what needs approval, and the **{field:ApprovalRequest.kind}** to see what sort of approval it is.\\n3. Check **{field:ApprovalRequest.requestedBy}** to see who asked.\\n\\n### See where a request stands\\n\\n1. Open the request.\\n2. Its **{field:ApprovalRequest.status}** shows whether it is still waiting, approved, rejected, sent back for changes, cancelled or expired.\\n3. **{field:ApprovalRequest.expiresAt}** is the deadline: after it a request can no longer be decided.\\n4. Once decided, **{field:ApprovalRequest.decidedAt}** shows when.\\n\\n### Read the history of a request\\n\\n1. Open the history.\\n2. Find the entries for the **{field:ApprovalEvent.requestId}** you are interested in.\\n3. Each entry shows **{field:ApprovalEvent.type}**, who did it in **{field:ApprovalEvent.actorId}**, and **{field:ApprovalEvent.occurredAt}**, oldest first.\\n4. A rejection or cancellation carries its **{field:ApprovalEvent.reason}**.\\n\\n### Read the rules for a kind of approval\\n\\n1. Open the policies.\\n2. Find the **{field:ApprovalPolicy.kind}** you want to know about.\\n3. **{field:ApprovalPolicy.requiredApprovals}** is how many different people must agree, and **{field:ApprovalPolicy.ttlMs}** is how long a request stays open.\\n4. **{field:ApprovalPolicy.requiredPermission}** names any extra permission a decider must hold.\\n","fieldRefs":["ApprovalEvent.actorId","ApprovalEvent.occurredAt","ApprovalEvent.reason","ApprovalEvent.requestId","ApprovalEvent.type","ApprovalPolicy.kind","ApprovalPolicy.requiredApprovals","ApprovalPolicy.requiredPermission","ApprovalPolicy.ttlMs","ApprovalRequest.decidedAt","ApprovalRequest.expiresAt","ApprovalRequest.kind","ApprovalRequest.requestedBy","ApprovalRequest.status","ApprovalRequest.summary"]},"demo":{"mode":"server","reasons":["Needs a server because its package depends on @happyvertical/smrt-profiles, @happyvertical/smrt-tenancy, @happyvertical/smrt-users, which do not build for a browser (#3617, #3624, #3626)."]}}],"smrtDependencies":["@happyvertical/smrt-core","@happyvertical/smrt-tenancy","@happyvertical/smrt-users"],"browser":{"status":"server-only","issues":["#3617","#3624","#3626"],"via":["@happyvertical/smrt-profiles","@happyvertical/smrt-tenancy","@happyvertical/smrt-users"]},"stampsConstructors":true}`));
7
7
  //#endregion
8
8
  //#region src/permissions.ts
9
9
  var CANCEL_ANY_APPROVAL_PERMISSION = "approvals.cancel-any";
@@ -147,11 +147,11 @@ var ApprovalRequest = class extends SmrtObject {
147
147
  *
148
148
  * @throws {ApprovalError} `APPROVAL_FORBIDDEN` for a persisted request.
149
149
  */
150
- async save() {
150
+ async save(options) {
151
151
  if (this.isPersisted) throw new ApprovalError("APPROVAL_FORBIDDEN", `ApprovalRequest ${this.id} is changed only through ApprovalService transitions.`);
152
152
  this.assertInsertAllowed();
153
153
  this.requireInsertOnSave();
154
- return await super.save();
154
+ return await super.save(options);
155
155
  }
156
156
  /**
157
157
  * Requests are durable records of a decision.
@@ -167,52 +167,63 @@ __decorateClass$5([tenantId()], ApprovalRequest.prototype, "tenantId", 2);
167
167
  __decorateClass$5([field({
168
168
  type: "text",
169
169
  required: true,
170
- readonly: true
170
+ readonly: true,
171
+ description: "What sort of approval this is, such as publishing a post."
171
172
  })], ApprovalRequest.prototype, "kind", 2);
172
173
  __decorateClass$5([field({
173
174
  type: "text",
174
175
  required: true,
175
- readonly: true
176
+ readonly: true,
177
+ description: "What kind of thing the request is about."
176
178
  })], ApprovalRequest.prototype, "subjectType", 2);
177
179
  __decorateClass$5([field({
178
180
  type: "text",
179
181
  required: true,
180
- readonly: true
182
+ readonly: true,
183
+ description: "Which thing the request is about."
181
184
  })], ApprovalRequest.prototype, "subjectId", 2);
182
185
  __decorateClass$5([field({
183
186
  type: "text",
184
187
  required: true,
185
- readonly: true
188
+ readonly: true,
189
+ description: "A fingerprint of the exact version that was put up for approval. If the thing changes, the approval no longer applies."
186
190
  })], ApprovalRequest.prototype, "subjectRevisionHash", 2);
187
191
  __decorateClass$5([field({
188
192
  type: "text",
189
193
  required: true,
190
- readonly: true
194
+ readonly: true,
195
+ description: "The reference the request is filed under, so asking twice does not open it twice."
191
196
  })], ApprovalRequest.prototype, "requestKey", 2);
192
197
  __decorateClass$5([field({
193
198
  type: "text",
194
199
  required: true,
195
- readonly: true
200
+ readonly: true,
201
+ description: "Who asked for the approval."
196
202
  })], ApprovalRequest.prototype, "requestedBy", 2);
197
203
  __decorateClass$5([field({
198
204
  type: "text",
199
- readonly: true
205
+ readonly: true,
206
+ description: "Whether a person, an assistant or an automated process asked."
200
207
  })], ApprovalRequest.prototype, "requestedByType", 2);
201
208
  __decorateClass$5([field({
202
209
  type: "text",
203
- readonly: true
210
+ readonly: true,
211
+ description: "A short description of what needs approval."
204
212
  })], ApprovalRequest.prototype, "summary", 2);
205
213
  __decorateClass$5([field({
206
214
  type: "text",
207
- readonly: true
215
+ readonly: true,
216
+ description: "Where the request stands: waiting, approved, rejected, changes requested, cancelled or expired."
208
217
  })], ApprovalRequest.prototype, "status", 2);
209
218
  __decorateClass$5([field({
210
219
  type: "integer",
211
- readonly: true
220
+ readonly: true,
221
+ description: "How many different people must agree."
212
222
  })], ApprovalRequest.prototype, "requiredApprovals", 2);
213
223
  __decorateClass$5([field({
214
224
  type: "integer",
215
- readonly: true
225
+ readonly: true,
226
+ description: "How many people have agreed so far."
216
227
  })], ApprovalRequest.prototype, "approvalCount", 2);
217
228
  __decorateClass$5([field({
218
229
  type: "text",
@@ -224,19 +235,23 @@ __decorateClass$5([field({
224
235
  })], ApprovalRequest.prototype, "version", 2);
225
236
  __decorateClass$5([field({
226
237
  type: "datetime",
227
- readonly: true
238
+ readonly: true,
239
+ description: "The deadline. After it the request can no longer be decided."
228
240
  })], ApprovalRequest.prototype, "expiresAt", 2);
229
241
  __decorateClass$5([field({
230
242
  type: "datetime",
231
- readonly: true
243
+ readonly: true,
244
+ description: "When the request was decided."
232
245
  })], ApprovalRequest.prototype, "decidedAt", 2);
233
246
  __decorateClass$5([field({
234
247
  type: "datetime",
235
- readonly: true
248
+ readonly: true,
249
+ description: "When the approval was used to let the action go ahead."
236
250
  })], ApprovalRequest.prototype, "consumedAt", 2);
237
251
  __decorateClass$5([field({
238
252
  type: "text",
239
- readonly: true
253
+ readonly: true,
254
+ description: "Who used the approval."
240
255
  })], ApprovalRequest.prototype, "consumedBy", 2);
241
256
  ApprovalRequest = __decorateClass$5([TenantScoped({ mode: "required" }), smrt({
242
257
  tableName: "approval_requests",
@@ -318,12 +333,12 @@ var ApprovalEvent = class extends SmrtObject {
318
333
  *
319
334
  * @throws {ApprovalError} `APPROVAL_FORBIDDEN` for a persisted event.
320
335
  */
321
- async save() {
336
+ async save(options) {
322
337
  if (this.isPersisted) throw new ApprovalError("APPROVAL_FORBIDDEN", `ApprovalEvent ${this.id} is append-only and cannot be updated.`);
323
338
  this.assertInsertAllowed();
324
339
  if (!this.occurredAt) this.occurredAt = /* @__PURE__ */ new Date();
325
340
  this.requireInsertOnSave();
326
- return await super.save();
341
+ return await super.save(options);
327
342
  }
328
343
  /**
329
344
  * Refuse any insert `ApprovalService` did not mint in the same transaction
@@ -352,7 +367,7 @@ var ApprovalEvent = class extends SmrtObject {
352
367
  };
353
368
  __publicField$4(ApprovalEvent, "__smrtPackage__", "@happyvertical/smrt-approvals");
354
369
  __decorateClass$4([tenantId()], ApprovalEvent.prototype, "tenantId", 2);
355
- __decorateClass$4([foreignKey(ApprovalRequest, {
370
+ __decorateClass$4([field({ description: "The request this entry belongs to." }), foreignKey(ApprovalRequest, {
356
371
  required: true,
357
372
  readonly: true,
358
373
  onDelete: "RESTRICT",
@@ -362,20 +377,24 @@ __decorateClass$4([foreignKey(ApprovalRequest, {
362
377
  __decorateClass$4([field({
363
378
  type: "text",
364
379
  required: true,
365
- readonly: true
380
+ readonly: true,
381
+ description: "What happened: created, approved, rejected, changes requested, cancelled, expired or used."
366
382
  })], ApprovalEvent.prototype, "type", 2);
367
383
  __decorateClass$4([field({
368
384
  type: "text",
369
385
  required: true,
370
- readonly: true
386
+ readonly: true,
387
+ description: "Who did it."
371
388
  })], ApprovalEvent.prototype, "actorId", 2);
372
389
  __decorateClass$4([field({
373
390
  type: "text",
374
- readonly: true
391
+ readonly: true,
392
+ description: "Whether a person, an assistant or an automated process did it."
375
393
  })], ApprovalEvent.prototype, "actorType", 2);
376
394
  __decorateClass$4([field({
377
395
  type: "text",
378
- readonly: true
396
+ readonly: true,
397
+ description: "The reason given, for example why a request was rejected or cancelled."
379
398
  })], ApprovalEvent.prototype, "reason", 2);
380
399
  __decorateClass$4([field({
381
400
  type: "text",
@@ -392,12 +411,14 @@ __decorateClass$4([field({
392
411
  })], ApprovalEvent.prototype, "voteKey", 2);
393
412
  __decorateClass$4([field({
394
413
  type: "datetime",
395
- readonly: true
414
+ readonly: true,
415
+ description: "When it happened."
396
416
  })], ApprovalEvent.prototype, "occurredAt", 2);
397
417
  __decorateClass$4([field({
398
418
  type: "boolean",
399
419
  readonly: true,
400
- default: false
420
+ default: false,
421
+ description: "Whether the person who asked also decided, where that is allowed."
401
422
  })], ApprovalEvent.prototype, "selfApproved", 2);
402
423
  __decorateClass$4([field({
403
424
  type: "text",
@@ -579,7 +600,7 @@ var ApprovalPolicy = class extends SmrtObject {
579
600
  * @throws {ApprovalError} `APPROVAL_KIND_UNKNOWN`,
580
601
  * `APPROVAL_POLICY_LOOSENS`, or `APPROVAL_INVALID`.
581
602
  */
582
- async save() {
603
+ async save(options) {
583
604
  this.requiredPermission = String(this.requiredPermission ?? "").trim();
584
605
  this.requiredApprovals = Number(this.requiredApprovals ?? 0);
585
606
  this.ttlMs = Number(this.ttlMs ?? 0);
@@ -588,19 +609,32 @@ var ApprovalPolicy = class extends SmrtObject {
588
609
  ttlMs: this.ttlMs,
589
610
  requiredPermission: this.requiredPermission
590
611
  });
591
- return await super.save();
612
+ return await super.save(options);
592
613
  }
593
614
  };
594
615
  __publicField$2(ApprovalPolicy, "__smrtPackage__", "@happyvertical/smrt-approvals");
595
616
  __decorateClass$2([tenantId()], ApprovalPolicy.prototype, "tenantId", 2);
596
617
  __decorateClass$2([field({
597
618
  type: "text",
598
- required: true
619
+ required: true,
620
+ description: "The sort of approval these rules apply to."
599
621
  })], ApprovalPolicy.prototype, "kind", 2);
600
- __decorateClass$2([field({ type: "integer" })], ApprovalPolicy.prototype, "requiredApprovals", 2);
601
- __decorateClass$2([field({ type: "integer" })], ApprovalPolicy.prototype, "ttlMs", 2);
602
- __decorateClass$2([field({ type: "text" })], ApprovalPolicy.prototype, "requiredPermission", 2);
603
- __decorateClass$2([field({ type: "text" })], ApprovalPolicy.prototype, "updatedBy", 2);
622
+ __decorateClass$2([field({
623
+ type: "integer",
624
+ description: "How many different people must agree. Zero keeps the usual number."
625
+ })], ApprovalPolicy.prototype, "requiredApprovals", 2);
626
+ __decorateClass$2([field({
627
+ type: "integer",
628
+ description: "How long a request stays open, in milliseconds. Zero keeps the usual time."
629
+ })], ApprovalPolicy.prototype, "ttlMs", 2);
630
+ __decorateClass$2([field({
631
+ type: "text",
632
+ description: "An extra permission a decider must hold. Leave empty for none."
633
+ })], ApprovalPolicy.prototype, "requiredPermission", 2);
634
+ __decorateClass$2([field({
635
+ type: "text",
636
+ description: "Who last changed these rules."
637
+ })], ApprovalPolicy.prototype, "updatedBy", 2);
604
638
  ApprovalPolicy = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
605
639
  tableName: "approval_policies",
606
640
  api: { include: ["list", "get"] },
@@ -663,6 +697,162 @@ ApprovalRequestCollection = __decorateClass([smrt({
663
697
  cli: false
664
698
  })], ApprovalRequestCollection);
665
699
  //#endregion
700
+ //#region src/recipes.ts
701
+ var ApprovalsRecipe = class extends SmrtRecipe {
702
+ static id = "approvals.requests";
703
+ static help = "./requests.recipe.md";
704
+ static label = "Approvals";
705
+ static summary = "See what is waiting for a yes, who decided what, and the rules each kind of approval follows.";
706
+ static synonyms = [
707
+ "approvals",
708
+ "approval requests",
709
+ "sign-off",
710
+ "sign off",
711
+ "authorisation",
712
+ "authorization",
713
+ "review queue",
714
+ "waiting for approval"
715
+ ];
716
+ static section = {
717
+ id: "approvals",
718
+ label: "Approvals",
719
+ icon: "briefcase",
720
+ description: "Who has to say yes before something happens."
721
+ };
722
+ static models = [
723
+ ApprovalRequest,
724
+ ApprovalEvent,
725
+ ApprovalPolicy
726
+ ];
727
+ static nav = [
728
+ {
729
+ label: "Requests",
730
+ model: ApprovalRequest,
731
+ icon: "fileText",
732
+ description: "Everything waiting for a yes or already decided, and where each one stands.",
733
+ noun: "request"
734
+ },
735
+ {
736
+ label: "History",
737
+ model: ApprovalEvent,
738
+ icon: "book",
739
+ description: "Who did what on each request, and when.",
740
+ noun: "history entry"
741
+ },
742
+ {
743
+ label: "Policies",
744
+ model: ApprovalPolicy,
745
+ icon: "settings",
746
+ description: "The rules for each kind of approval: how many people must agree and how long a request lasts.",
747
+ noun: "policy"
748
+ }
749
+ ];
750
+ static options = {
751
+ ApprovalRequest: { fields: {
752
+ summary: { order: 1 },
753
+ kind: { order: 2 },
754
+ status: { order: 3 },
755
+ requestedBy: {
756
+ label: "Requested by",
757
+ order: 4
758
+ },
759
+ requestedByType: {
760
+ label: "Requested by a",
761
+ order: 5
762
+ },
763
+ expiresAt: {
764
+ label: "Expires",
765
+ order: 6
766
+ },
767
+ decidedAt: {
768
+ label: "Decided on",
769
+ order: 7
770
+ },
771
+ subjectType: {
772
+ label: "What it is about",
773
+ visibility: "advanced"
774
+ },
775
+ subjectId: {
776
+ label: "Which one",
777
+ visibility: "advanced"
778
+ },
779
+ requiredApprovals: {
780
+ label: "Approvals needed",
781
+ visibility: "advanced"
782
+ },
783
+ approvalCount: {
784
+ label: "Approvals so far",
785
+ visibility: "advanced"
786
+ },
787
+ consumedAt: {
788
+ label: "Used on",
789
+ visibility: "advanced"
790
+ },
791
+ consumedBy: {
792
+ label: "Used by",
793
+ visibility: "advanced"
794
+ },
795
+ tenantId: { visibility: "hidden" },
796
+ subjectRevisionHash: { visibility: "hidden" },
797
+ requestKey: { visibility: "hidden" },
798
+ requiredPermissions: { visibility: "hidden" },
799
+ version: { visibility: "hidden" }
800
+ } },
801
+ ApprovalEvent: { fields: {
802
+ requestId: {
803
+ label: "Request",
804
+ order: 1
805
+ },
806
+ type: {
807
+ label: "What happened",
808
+ order: 2
809
+ },
810
+ actorId: {
811
+ label: "Who",
812
+ order: 3
813
+ },
814
+ actorType: {
815
+ label: "Who it was",
816
+ order: 4
817
+ },
818
+ reason: { order: 5 },
819
+ occurredAt: {
820
+ label: "When",
821
+ order: 6
822
+ },
823
+ selfApproved: {
824
+ label: "Decided by the requester",
825
+ visibility: "advanced"
826
+ },
827
+ tenantId: { visibility: "hidden" },
828
+ subjectRevisionHash: { visibility: "hidden" },
829
+ sequence: { visibility: "hidden" },
830
+ voteKey: { visibility: "hidden" },
831
+ selfApprovalPermission: { visibility: "hidden" }
832
+ } },
833
+ ApprovalPolicy: { fields: {
834
+ kind: { order: 1 },
835
+ requiredApprovals: {
836
+ label: "Approvals needed",
837
+ order: 2
838
+ },
839
+ ttlMs: {
840
+ label: "Time limit in milliseconds",
841
+ order: 3
842
+ },
843
+ requiredPermission: {
844
+ label: "Extra permission needed",
845
+ order: 4
846
+ },
847
+ updatedBy: {
848
+ label: "Last changed by",
849
+ order: 5
850
+ },
851
+ tenantId: { visibility: "hidden" }
852
+ } }
853
+ };
854
+ };
855
+ //#endregion
666
856
  //#region src/service.ts
667
857
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
668
858
  var MAX_TOKEN_LENGTH = 256;
@@ -1326,6 +1516,6 @@ var ApprovalService = class ApprovalService {
1326
1516
  //#region src/index.ts
1327
1517
  ensureApprovalPermissionsRegistered();
1328
1518
  //#endregion
1329
- export { APPROVAL_EVENT_TYPES, APPROVAL_PERMISSION_DEFINITIONS, APPROVAL_PRINCIPAL_TYPES, APPROVAL_STATUSES, ApprovalError, ApprovalEvent, ApprovalEventCollection, ApprovalPolicy, ApprovalPolicyCollection, ApprovalRequest, ApprovalRequestCollection, ApprovalService, CANCEL_ANY_APPROVAL_PERMISSION, DEFAULT_APPROVAL_TTL_MS, MANAGE_APPROVAL_POLICY_PERMISSION, MAX_APPROVAL_TTL_MS, MAX_REQUIRED_APPROVALS, MIN_APPROVAL_TTL_MS, approvalPrincipalFromPermissions, assertPolicyTightens, defineApprovalKind, effectiveRules, ensureApprovalPermissionsRegistered, getApprovalKind, listApprovalKinds, registerApprovalPermissions, requireApprovalKind, unregisterApprovalKind };
1519
+ export { APPROVAL_EVENT_TYPES, APPROVAL_PERMISSION_DEFINITIONS, APPROVAL_PRINCIPAL_TYPES, APPROVAL_STATUSES, ApprovalError, ApprovalEvent, ApprovalEventCollection, ApprovalPolicy, ApprovalPolicyCollection, ApprovalRequest, ApprovalRequestCollection, ApprovalService, ApprovalsRecipe, CANCEL_ANY_APPROVAL_PERMISSION, DEFAULT_APPROVAL_TTL_MS, MANAGE_APPROVAL_POLICY_PERMISSION, MAX_APPROVAL_TTL_MS, MAX_REQUIRED_APPROVALS, MIN_APPROVAL_TTL_MS, approvalPrincipalFromPermissions, assertPolicyTightens, defineApprovalKind, effectiveRules, ensureApprovalPermissionsRegistered, getApprovalKind, listApprovalKinds, registerApprovalPermissions, requireApprovalKind, unregisterApprovalKind };
1330
1520
 
1331
1521
  //# sourceMappingURL=index.js.map