@happyvertical/smrt-secrets 0.55.12 → 0.55.13
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/AGENTS.md +5 -1
- package/dist/chunks/{SecretService-WkNvPwQJ.js → SecretService-3iOtNnBI.js} +15 -9
- package/dist/chunks/SecretService-3iOtNnBI.js.map +1 -0
- package/dist/chunks/{TenantKey-B6RgWu-x.js → TenantKey-ijZovCsO.js} +2 -2
- package/dist/chunks/{TenantKey-B6RgWu-x.js.map → TenantKey-ijZovCsO.js.map} +1 -1
- package/dist/collections/SecretAuditLogCollection.d.ts +15 -7
- package/dist/collections/SecretAuditLogCollection.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/manifest.json +1 -1
- package/dist/models/SecretAuditLog.d.ts.map +1 -1
- package/dist/models/index.js +1 -1
- package/dist/services/SecretService.js +1 -1
- package/dist/smrt-knowledge.json +5 -5
- package/package.json +8 -8
- package/dist/chunks/SecretService-WkNvPwQJ.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TenantKey-B6RgWu-x.js","names":[],"sources":["../../src/__smrt-register__.ts","../../src/models/SecretAuditLog.ts","../../src/models/Secret.ts","../../src/models/TenantKey.ts"],"sourcesContent":["// Generated by @happyvertical/smrt-core smrtPlugin at library build time.\n// The package manifest is inlined so self-registration cannot miss when a\n// downstream bundler relocates this module away from dist/manifest.json\n// (https://github.com/happyvertical/smrt/issues/1506,\n// https://github.com/happyvertical/smrt/issues/1507).\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\nObjectRegistry.registerPackageManifest(JSON.parse(\"{\\\"version\\\":\\\"1.0.0\\\",\\\"timestamp\\\":0,\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"packageVersion\\\":\\\"0.55.12\\\",\\\"objects\\\":{\\\"@happyvertical/smrt-secrets:SecretAuditLogCollection\\\":{\\\"name\\\":\\\"secretauditlogcollection\\\",\\\"className\\\":\\\"SecretAuditLogCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:SecretAuditLogCollection\\\",\\\"collection\\\":\\\"secretauditlogs\\\",\\\"description\\\":\\\"Collection for managing SecretAuditLog objects\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/collections/SecretAuditLogCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"listLogs\\\":{\\\"name\\\":\\\"listLogs\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"ListAuditLogsOptions\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SecretAuditLog[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getSecretHistory\\\":{\\\"name\\\":\\\"getSecretHistory\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"secretName\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"limit\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SecretAuditLog[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getUserActivity\\\":{\\\"name\\\":\\\"getUserActivity\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"userId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"limit\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SecretAuditLog[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getRecentFailures\\\":{\\\"name\\\":\\\"getRecentFailures\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"limit\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SecretAuditLog[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getRecentDenials\\\":{\\\"name\\\":\\\"getRecentDenials\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"limit\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SecretAuditLog[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"countByAction\\\":{\\\"name\\\":\\\"countByAction\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"since\\\",\\\"type\\\":\\\"Date\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<Record<SecretAuditAction, number>>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"countByResult\\\":{\\\"name\\\":\\\"countByResult\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"since\\\",\\\"type\\\":\\\"Date\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<Record<SecretAuditResult, number>>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"cleanup\\\":{\\\"name\\\":\\\"cleanup\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"olderThanDays\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<number>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"SecretAuditLog\\\",\\\"exportName\\\":\\\"SecretAuditLogCollection\\\",\\\"collectionExportName\\\":\\\"SecretAuditLogCollectionCollection\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"secret_audit_logs\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"secret_audit_logs\\\\\\\" (\\\\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,\\\\n \\\\\\\"secret_id\\\\\\\" UUID,\\\\n \\\\\\\"secret_name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"user_id\\\\\\\" UUID,\\\\n \\\\\\\"action\\\\\\\" TEXT DEFAULT 'read',\\\\n \\\\\\\"result\\\\\\\" TEXT DEFAULT 'success',\\\\n \\\\\\\"ip_address\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"user_agent\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"details\\\\\\\" JSON 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\\\":false,\\\"unique\\\":false},\\\"secret_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"secret_name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"user_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"action\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"read\\\"},\\\"result\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"success\\\"},\\\"ip_address\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"user_agent\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"details\\\":{\\\"type\\\":\\\"JSON\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":{}}},\\\"indexes\\\":[{\\\"name\\\":\\\"secret_audit_logs_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"secret_audit_logs_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"secret_audit_logs_secret_id_idx\\\",\\\"columns\\\":[\\\"secret_id\\\"]},{\\\"name\\\":\\\"secret_audit_logs_user_id_idx\\\",\\\"columns\\\":[\\\"user_id\\\"]}],\\\"version\\\":\\\"af0d679d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets\\\"},\\\"@happyvertical/smrt-secrets:SecretCollection\\\":{\\\"name\\\":\\\"secretcollection\\\",\\\"className\\\":\\\"SecretCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:SecretCollection\\\",\\\"collection\\\":\\\"secrets\\\",\\\"description\\\":\\\"Collection for managing Secret objects\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/collections/SecretCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"findByName\\\":{\\\"name\\\":\\\"findByName\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"name\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<Secret | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listSecrets\\\":{\\\"name\\\":\\\"listSecrets\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"ListSecretsOptions\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<Secret[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listActive\\\":{\\\"name\\\":\\\"listActive\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<Secret[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listByCategory\\\":{\\\"name\\\":\\\"listByCategory\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"category\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<Secret[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listExpiring\\\":{\\\"name\\\":\\\"listExpiring\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"daysAhead\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<Secret[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getCategories\\\":{\\\"name\\\":\\\"getCategories\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<string[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"countByStatus\\\":{\\\"name\\\":\\\"countByStatus\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<Record<SecretStatus, number>>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"deleteByName\\\":{\\\"name\\\":\\\"deleteByName\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"name\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<boolean>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"Secret\\\",\\\"exportName\\\":\\\"SecretCollection\\\",\\\"collectionExportName\\\":\\\"SecretCollectionCollection\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"secrets\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"secrets\\\\\\\" (\\\\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,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"description\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"category\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"encrypted_value\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"key_version\\\\\\\" INTEGER DEFAULT 1,\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"expires_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"last_accessed_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"access_count\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"metadata\\\\\\\" JSON 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\\\":false,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"description\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"category\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"encrypted_value\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"key_version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":1},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"expires_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"last_accessed_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"access_count\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"metadata\\\":{\\\"type\\\":\\\"JSON\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":{}}},\\\"indexes\\\":[{\\\"name\\\":\\\"secrets_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"secrets_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"6298a980\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets\\\"},\\\"@happyvertical/smrt-secrets:TenantKeyCollection\\\":{\\\"name\\\":\\\"tenantkeycollection\\\",\\\"className\\\":\\\"TenantKeyCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:TenantKeyCollection\\\",\\\"collection\\\":\\\"tenantkeys\\\",\\\"description\\\":\\\"Collection for managing TenantKey objects\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/collections/TenantKeyCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"getActiveKey\\\":{\\\"name\\\":\\\"getActiveKey\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantKey | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listKeyVersions\\\":{\\\"name\\\":\\\"listKeyVersions\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantKey[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getKeyVersion\\\":{\\\"name\\\":\\\"getKeyVersion\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"version\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantKey | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findKeysNeedingRotation\\\":{\\\"name\\\":\\\"findKeysNeedingRotation\\\",\\\"async\\\":true,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Promise<TenantKey[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listAllActiveKeys\\\":{\\\"name\\\":\\\"listAllActiveKeys\\\",\\\"async\\\":true,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Promise<TenantKey[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"countByStatus\\\":{\\\"name\\\":\\\"countByStatus\\\",\\\"async\\\":true,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Promise<Record<TenantKeyStatus, number>>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"markCompromised\\\":{\\\"name\\\":\\\"markCompromised\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"keyId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<boolean>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"cleanupRetiredKeys\\\":{\\\"name\\\":\\\"cleanupRetiredKeys\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"olderThanDays\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<number>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"TenantKey\\\",\\\"exportName\\\":\\\"TenantKeyCollection\\\",\\\"collectionExportName\\\":\\\"TenantKeyCollectionCollection\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"tenant_keys\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"tenant_keys\\\\\\\" (\\\\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,\\\\n \\\\\\\"wrapped_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"amk_key_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"version\\\\\\\" INTEGER DEFAULT 1,\\\\n \\\\\\\"rotate_after\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"retired_at\\\\\\\" TIMESTAMP\\\\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\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"wrapped_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"amk_key_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":1},\\\"rotate_after\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"retired_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"tenant_keys_tenant_id_slug_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"tenant_keys_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]}],\\\"version\\\":\\\"abc3474a\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets\\\"},\\\"@happyvertical/smrt-secrets:Secret\\\":{\\\"name\\\":\\\"secret\\\",\\\"className\\\":\\\"Secret\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:Secret\\\",\\\"collection\\\":\\\"secrets\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/models/Secret.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"autoFilter\\\":true,\\\"autoPopulate\\\":true,\\\"allowSuperAdminBypass\\\":false}}},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"description\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"category\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"encryptedValue\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"keyVersion\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":1},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"active\\\",\\\"enum\\\":[\\\"active\\\",\\\"disabled\\\",\\\"expired\\\"]},\\\"expiresAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"lastAccessedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"accessCount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"metadata\\\":{\\\"type\\\":\\\"json\\\",\\\"required\\\":false,\\\"default\\\":{}}},\\\"methods\\\":{\\\"isActive\\\":{\\\"name\\\":\\\"isActive\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isExpired\\\":{\\\"name\\\":\\\"isExpired\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isUsable\\\":{\\\"name\\\":\\\"isUsable\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"recordAccess\\\":{\\\"name\\\":\\\"recordAccess\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"disable\\\":{\\\"name\\\":\\\"disable\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"enable\\\":{\\\"name\\\":\\\"enable\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"sensitive\\\":true,\\\"tenantScoped\\\":true,\\\"api\\\":{\\\"include\\\":[]},\\\"mcp\\\":{\\\"include\\\":[]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\"],\\\"skipApiCheck\\\":true},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"Secret\\\",\\\"collectionExportName\\\":\\\"SecretCollection\\\",\\\"displayLabelField\\\":\\\"name\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"secrets\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"secrets\\\\\\\" (\\\\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,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"description\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"category\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"encrypted_value\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"key_version\\\\\\\" INTEGER DEFAULT 1,\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"expires_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"last_accessed_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"access_count\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"metadata\\\\\\\" JSON 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\\\":false,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"description\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"category\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"encrypted_value\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"key_version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":1},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"expires_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"last_accessed_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"access_count\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"metadata\\\":{\\\"type\\\":\\\"JSON\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":{}}},\\\"indexes\\\":[{\\\"name\\\":\\\"secrets_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"secrets_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"6298a980\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets/models\\\"},\\\"@happyvertical/smrt-secrets:SecretAuditLog\\\":{\\\"name\\\":\\\"secretauditlog\\\",\\\"className\\\":\\\"SecretAuditLog\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:SecretAuditLog\\\",\\\"collection\\\":\\\"secretauditlogs\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/models/SecretAuditLog.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"autoFilter\\\":true,\\\"autoPopulate\\\":true,\\\"allowSuperAdminBypass\\\":false}}},\\\"secretId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"Secret\\\",\\\"_meta\\\":{\\\"constraint\\\":false}},\\\"secretName\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"userId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":false,\\\"related\\\":\\\"@happyvertical/smrt-users:User\\\"},\\\"action\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"read\\\",\\\"enum\\\":[\\\"create\\\",\\\"read\\\",\\\"update\\\",\\\"delete\\\",\\\"rotate_key\\\",\\\"disable\\\",\\\"enable\\\",\\\"expire\\\"]},\\\"result\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"success\\\",\\\"enum\\\":[\\\"success\\\",\\\"failure\\\",\\\"denied\\\"]},\\\"ipAddress\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"userAgent\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"details\\\":{\\\"type\\\":\\\"json\\\",\\\"required\\\":false,\\\"default\\\":{}}},\\\"methods\\\":{\\\"isSuccess\\\":{\\\"name\\\":\\\"isSuccess\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isFailure\\\":{\\\"name\\\":\\\"isFailure\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isDenied\\\":{\\\"name\\\":\\\"isDenied\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isReadAction\\\":{\\\"name\\\":\\\"isReadAction\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isWriteAction\\\":{\\\"name\\\":\\\"isWriteAction\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isKeyOperation\\\":{\\\"name\\\":\\\"isKeyOperation\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tenantScoped\\\":true,\\\"api\\\":{\\\"include\\\":[]},\\\"mcp\\\":{\\\"include\\\":[]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\"],\\\"skipApiCheck\\\":true},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"SecretAuditLog\\\",\\\"collectionExportName\\\":\\\"SecretAuditLogCollection\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"secret_audit_logs\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"secret_audit_logs\\\\\\\" (\\\\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,\\\\n \\\\\\\"secret_id\\\\\\\" UUID,\\\\n \\\\\\\"secret_name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"user_id\\\\\\\" UUID,\\\\n \\\\\\\"action\\\\\\\" TEXT DEFAULT 'read',\\\\n \\\\\\\"result\\\\\\\" TEXT DEFAULT 'success',\\\\n \\\\\\\"ip_address\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"user_agent\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"details\\\\\\\" JSON 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\\\":false,\\\"unique\\\":false},\\\"secret_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"secret_name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"user_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"action\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"read\\\"},\\\"result\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"success\\\"},\\\"ip_address\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"user_agent\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"details\\\":{\\\"type\\\":\\\"JSON\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":{}}},\\\"indexes\\\":[{\\\"name\\\":\\\"secret_audit_logs_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"secret_audit_logs_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"secret_audit_logs_secret_id_idx\\\",\\\"columns\\\":[\\\"secret_id\\\"]},{\\\"name\\\":\\\"secret_audit_logs_user_id_idx\\\",\\\"columns\\\":[\\\"user_id\\\"]}],\\\"version\\\":\\\"af0d679d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets/models\\\"},\\\"@happyvertical/smrt-secrets:TenantKey\\\":{\\\"name\\\":\\\"tenantkey\\\",\\\"className\\\":\\\"TenantKey\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:TenantKey\\\",\\\"collection\\\":\\\"tenantkeys\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/models/TenantKey.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\"}},\\\"wrappedKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"amkKeyId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"active\\\",\\\"enum\\\":[\\\"active\\\",\\\"rotating\\\",\\\"retired\\\",\\\"compromised\\\"]},\\\"version\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":1},\\\"rotateAfter\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"retiredAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false}},\\\"methods\\\":{\\\"isActive\\\":{\\\"name\\\":\\\"isActive\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"needsRotation\\\":{\\\"name\\\":\\\"needsRotation\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isRetired\\\":{\\\"name\\\":\\\"isRetired\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isCompromised\\\":{\\\"name\\\":\\\"isCompromised\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"canDecrypt\\\":{\\\"name\\\":\\\"canDecrypt\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"canEncrypt\\\":{\\\"name\\\":\\\"canEncrypt\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"retire\\\":{\\\"name\\\":\\\"retire\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"markCompromised\\\":{\\\"name\\\":\\\"markCompromised\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"sensitive\\\":true,\\\"api\\\":{\\\"include\\\":[]},\\\"mcp\\\":{\\\"include\\\":[]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"],\\\"skipApiCheck\\\":true},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"TenantKey\\\",\\\"collectionExportName\\\":\\\"TenantKeyCollection\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"tenant_keys\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"tenant_keys\\\\\\\" (\\\\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,\\\\n \\\\\\\"wrapped_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"amk_key_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"version\\\\\\\" INTEGER DEFAULT 1,\\\\n \\\\\\\"rotate_after\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"retired_at\\\\\\\" TIMESTAMP\\\\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\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"wrapped_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"amk_key_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":1},\\\"rotate_after\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"retired_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"tenant_keys_tenant_id_slug_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"tenant_keys_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]}],\\\"version\\\":\\\"abc3474a\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets/models\\\"}},\\\"moduleType\\\":\\\"smrt\\\",\\\"smrtDependencies\\\":[\\\"@happyvertical/smrt-core\\\",\\\"@happyvertical/smrt-tenancy\\\"],\\\"browser\\\":{\\\"status\\\":\\\"server-only\\\",\\\"issues\\\":[\\\"#3624\\\",\\\"#3627\\\"],\\\"reason\\\":\\\"@happyvertical/secrets (node:child_process, node:crypto) and sql\\\",\\\"via\\\":[\\\"@happyvertical/smrt-tenancy\\\"]},\\\"stampsConstructors\\\":true}\"));\n","/**\n * SecretAuditLog model - Audit trail for secret operations\n * @packageDocumentation\n */\n\nimport type {\n SmrtCreateInput,\n SmrtObjectOptions,\n} from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\n\n/**\n * Secret audit action types\n */\nexport type SecretAuditAction =\n | 'create'\n | 'read'\n | 'update'\n | 'delete'\n | 'rotate_key'\n | 'disable'\n | 'enable'\n | 'expire';\n\n/**\n * Audit result types\n */\nexport type SecretAuditResult = 'success' | 'failure' | 'denied';\n\n/**\n * Constructor options for {@link SecretAuditLog}. Each field is optional and\n * mirrors a persisted column.\n */\nexport interface SecretAuditLogOptions extends SmrtObjectOptions {\n tenantId?: string | null;\n secretId?: string | null;\n secretName?: string;\n userId?: string | null;\n action?: SecretAuditAction;\n result?: SecretAuditResult;\n ipAddress?: string;\n userAgent?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * SecretAuditLog records all operations on secrets for compliance\n * and security monitoring.\n *\n * Every secret operation (create, read, update, delete, key rotation)\n * is logged with the user, action, result, and relevant details.\n *\n * **Retention**: Audit logs should be retained according to your\n * compliance requirements (typically 1-7 years).\n *\n * @example\n * ```typescript\n * // Query recent audit logs\n * const logs = await auditLogs.list({\n * where: { tenantId: 'tenant-123' },\n * orderBy: 'created_at DESC',\n * limit: 100\n * });\n *\n * // Filter by action\n * const reads = await auditLogs.list({\n * where: {\n * tenantId: 'tenant-123',\n * action: 'read'\n * }\n * });\n *\n * // Filter by secret name\n * const apiKeyLogs = await auditLogs.list({\n * where: {\n * tenantId: 'tenant-123',\n * secretName: 'stripe-api-key'\n * }\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped({ mode: 'optional' })`):\n// `SecretAuditLog` uses the inline `tenantScoped: true` form on `@smrt()` rather than\n// the dedicated `@TenantScoped` decorator. Audit-trail queries are read-mostly and run\n// in mixed contexts — under a tenant for tenant-scoped reports, and (prospectively)\n// under super-admin bypass for compliance review. Cross-tenant audit queries should\n// be wrapped in `withSuperAdminBypass()` from `@happyvertical/smrt-tenancy` at the\n// call site; this package has no such call sites today, so the pattern is\n// prescriptive guidance for compliance tooling rather than current practice. See\n// `packages/secrets/CLAUDE.md` \"Known exceptions to monorepo standards\" for context.\n@smrt({\n tenantScoped: true,\n api: { include: [] }, // No API exposure\n mcp: { include: [] }, // No MCP exposure\n // CLI runs in-process for compliance review; HTTP exposure is intentionally\n // excluded, so skipApiCheck acknowledges the cli.include / api.include divergence.\n cli: { include: ['list'], skipApiCheck: true },\n})\nexport class SecretAuditLog extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-secrets\";\n /**\n * Tenant associated with the audited secret operation.\n */\n tenantId: string | null = null;\n\n /**\n * ID of the secret (may identify a secret that has since been deleted).\n *\n * Compliance audit rows intentionally outlive their source secret, so this\n * remains an app-side relationship without a physical database constraint.\n */\n @foreignKey('Secret', { constraint: false })\n secretId: string | null = null;\n\n /**\n * Name of the secret at the time of the operation\n */\n secretName: string = '';\n\n /**\n * ID of the user who performed the action, or `null` for system-initiated\n * operations with no authenticated user. Stored as a native `uuid` column on\n * Postgres, so a non-UUID actor sentinel must never reach it —\n * {@link createAuditEntry} normalizes the `'system'` sentinel to null (#1444).\n */\n @crossPackageRef('@happyvertical/smrt-users:User')\n userId: string | null = null;\n\n /**\n * The action that was performed\n */\n action: SecretAuditAction = 'read';\n\n /**\n * Result of the operation\n */\n result: SecretAuditResult = 'success';\n\n /**\n * IP address of the client (if available)\n */\n ipAddress: string = '';\n\n /**\n * User agent string (if available)\n */\n userAgent: string = '';\n\n /**\n * Additional context about the operation\n */\n details: Record<string, unknown> = {};\n\n constructor(options: SecretAuditLogOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) {\n this.tenantId = options.tenantId;\n }\n if (options.secretId !== undefined) this.secretId = options.secretId;\n if (options.secretName !== undefined) this.secretName = options.secretName;\n if (options.userId !== undefined) this.userId = options.userId;\n if (options.action !== undefined) this.action = options.action;\n if (options.result !== undefined) this.result = options.result;\n if (options.ipAddress !== undefined) this.ipAddress = options.ipAddress;\n if (options.userAgent !== undefined) this.userAgent = options.userAgent;\n if (options.details !== undefined) this.details = options.details;\n }\n\n /**\n * Check if this was a successful operation\n */\n isSuccess(): boolean {\n return this.result === 'success';\n }\n\n /**\n * Check if this was a failed operation\n */\n isFailure(): boolean {\n return this.result === 'failure';\n }\n\n /**\n * Check if this was a denied operation (permission denied)\n */\n isDenied(): boolean {\n return this.result === 'denied';\n }\n\n /**\n * Check if this is a read operation\n */\n isReadAction(): boolean {\n return this.action === 'read';\n }\n\n /**\n * Check if this is a write operation (create, update, delete)\n */\n isWriteAction(): boolean {\n return ['create', 'update', 'delete'].includes(this.action);\n }\n\n /**\n * Check if this is a key operation\n */\n isKeyOperation(): boolean {\n return this.action === 'rotate_key';\n }\n}\n\nconst UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Create an audit log entry for a secret operation\n */\nexport function createAuditEntry(params: {\n secretId?: string | null;\n secretName: string;\n tenantId?: string | null;\n userId?: string | null;\n action: SecretAuditAction;\n result: SecretAuditResult;\n ipAddress?: string;\n userAgent?: string;\n details?: Record<string, unknown>;\n}): SmrtCreateInput<SecretAuditLog> {\n const tenantId =\n params.tenantId === undefined || params.tenantId === 'system'\n ? null\n : params.tenantId;\n\n // The `userId` column is a native `uuid` on Postgres. A missing actor and the\n // `'system'`/empty sentinels are not valid UUIDs, so normalize them all to\n // null — a system-initiated operation has no authenticated user. Callers may\n // pass `null`/`undefined` directly to express that (#1444).\n // Any other value that is not a uuid (an email-login identity, a service\n // name) would fail the insert and with it the audited operation; record it\n // in `details.actorId` instead so the actor is never lost.\n const rawUserId =\n params.userId == null || params.userId === 'system' || params.userId === ''\n ? null\n : params.userId;\n const userId =\n rawUserId !== null && UUID_PATTERN.test(rawUserId) ? rawUserId : null;\n const details =\n rawUserId !== null && userId === null\n ? { ...(params.details ?? {}), actorId: rawUserId }\n : (params.details ?? {});\n\n const entry: SmrtCreateInput<SecretAuditLog> = {\n secretId: params.secretId ?? null,\n secretName: params.secretName,\n userId,\n action: params.action,\n result: params.result,\n ipAddress: params.ipAddress ?? '',\n userAgent: params.userAgent ?? '',\n details,\n tenantId,\n };\n return entry;\n}\n","/**\n * Secret model - Tenant-scoped encrypted secrets storage\n * @packageDocumentation\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { SmrtObject, smrt } from '@happyvertical/smrt-core';\n\n/**\n * Secret status values\n */\nexport type SecretStatus = 'active' | 'disabled' | 'expired';\n\n/**\n * Constructor options for {@link Secret}. Each field is optional and mirrors a\n * persisted column; date fields also accept the serialized forms accepted by\n * `new Date()` so hydrated rows coerce cleanly.\n */\nexport interface SecretOptions extends SmrtObjectOptions {\n tenantId?: string;\n name?: string;\n description?: string;\n category?: string;\n encryptedValue?: string;\n keyVersion?: number;\n status?: SecretStatus;\n expiresAt?: Date | string | number | null;\n lastAccessedAt?: Date | string | number | null;\n accessCount?: number;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Secret represents an encrypted value stored per-tenant.\n *\n * Secrets are tenant-scoped and use envelope encryption:\n * - Each tenant has their own Data Encryption Key (TDEK)\n * - The TDEK is wrapped by the Application Master Key (AMK)\n * - Secret values are encrypted by the unwrapped TDEK\n *\n * **Security**: This model deliberately excludes API and MCP exposure\n * to prevent accidental secret leakage. Secrets are only accessible\n * via CLI commands or direct service calls.\n *\n * @example\n * ```typescript\n * import { SecretService } from '@happyvertical/smrt-secrets';\n *\n * const service = await SecretService.create({ db });\n *\n * await withTenant({ tenantId: 'tenant-123' }, async () => {\n * // Store a secret\n * await service.store('api-key', 'sk_live_xxx', { category: 'stripe' });\n *\n * // Retrieve (auto-decrypts)\n * const apiKey = await service.retrieve('api-key');\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped({ mode: 'optional' })`):\n// `Secret` uses the inline `tenantScoped: true` form on `@smrt()` rather than the\n// dedicated `@TenantScoped` decorator from `@happyvertical/smrt-tenancy`. The boolean\n// form gives us required-mode tenant scoping without depending on the tenancy package\n// at the model layer, while `SecretService` performs manual scoping by setting\n// `context = tenantId` on each row. The `(slug, context)` upsert key derived from the\n// base `SmrtObject` fields is what gives different tenants isolated namespaces for\n// secret names — switching to the decorator without changing the upsert key would\n// surface false-positive name collisions across tenants. See\n// `packages/secrets/CLAUDE.md` \"Known exceptions to monorepo standards\" for context.\n@smrt({\n // Stores key material; never in the change feed (#2937).\n sensitive: true,\n tenantScoped: true,\n // NO API or MCP exposure for security\n api: { include: [] },\n mcp: { include: [] },\n // CLI runs in-process; secrets must never be reachable over HTTP, so\n // skipApiCheck acknowledges the cli.include / api.include divergence.\n cli: { include: ['list'], skipApiCheck: true }, // Only list names, not values\n})\nexport class Secret extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-secrets\";\n /**\n * Tenant that owns this secret. Also stored in context for per-tenant name uniqueness.\n */\n tenantId: string = '';\n\n /**\n * Unique name for the secret within the tenant\n */\n name: string = '';\n\n /**\n * Human-readable description\n */\n description: string = '';\n\n /**\n * Category for organization (e.g., 'database', 'api-key', 'oauth')\n */\n category: string = '';\n\n /**\n * JSON-encoded EncryptedEnvelope from @happyvertical/secrets\n */\n encryptedValue: string = '';\n\n /**\n * Version of the tenant key used to encrypt this secret\n */\n keyVersion: number = 1;\n\n /**\n * Current status of the secret\n */\n status: SecretStatus = 'active';\n\n /**\n * Optional expiration date\n */\n expiresAt: Date | null = null;\n\n /**\n * Last time this secret was accessed (decrypted)\n */\n lastAccessedAt: Date | null = null;\n\n /**\n * Number of times this secret has been accessed\n */\n accessCount: number = 0;\n\n /**\n * Additional metadata stored with the secret\n */\n metadata: Record<string, unknown> = {};\n\n constructor(options: SecretOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.name !== undefined) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.category !== undefined) this.category = options.category;\n if (options.encryptedValue !== undefined)\n this.encryptedValue = options.encryptedValue;\n if (options.keyVersion !== undefined) this.keyVersion = options.keyVersion;\n if (options.status !== undefined) this.status = options.status;\n if (options.expiresAt !== undefined) {\n this.expiresAt =\n options.expiresAt instanceof Date\n ? options.expiresAt\n : options.expiresAt\n ? new Date(options.expiresAt)\n : null;\n }\n if (options.lastAccessedAt !== undefined) {\n this.lastAccessedAt =\n options.lastAccessedAt instanceof Date\n ? options.lastAccessedAt\n : options.lastAccessedAt\n ? new Date(options.lastAccessedAt)\n : null;\n }\n if (options.accessCount !== undefined)\n this.accessCount = options.accessCount;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n /**\n * Check if the secret is currently active\n */\n isActive(): boolean {\n return this.status === 'active';\n }\n\n /**\n * Check if the secret has expired\n */\n isExpired(): boolean {\n if (!this.expiresAt) return false;\n return new Date() >= this.expiresAt;\n }\n\n /**\n * Check if the secret can be used (active and not expired)\n */\n isUsable(): boolean {\n return this.isActive() && !this.isExpired();\n }\n\n /**\n * Record an access to this secret\n */\n recordAccess(): void {\n this.lastAccessedAt = new Date();\n this.accessCount += 1;\n }\n\n /**\n * Disable the secret\n */\n disable(): void {\n this.status = 'disabled';\n }\n\n /**\n * Enable the secret\n */\n enable(): void {\n this.status = 'active';\n }\n}\n","/**\n * TenantKey model - Tracks per-tenant Data Encryption Keys (TDEKs)\n * @packageDocumentation\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\n\n/**\n * Key status values\n */\nexport type TenantKeyStatus = 'active' | 'rotating' | 'retired' | 'compromised';\n\n/**\n * Constructor options for {@link TenantKey}. Each field is optional and mirrors\n * a persisted column; date fields also accept the serialized forms accepted by\n * `new Date()` so hydrated rows coerce cleanly.\n */\nexport interface TenantKeyOptions extends SmrtObjectOptions {\n tenantId?: string;\n wrappedKey?: string;\n amkKeyId?: string;\n status?: TenantKeyStatus;\n version?: number;\n rotateAfter?: Date | string | number | null;\n retiredAt?: Date | string | number | null;\n}\n\n/**\n * TenantKey tracks the per-tenant Data Encryption Keys (TDEKs).\n *\n * Each tenant has one or more TDEKs stored in wrapped form. The wrapped key\n * can only be decrypted using the Application Master Key (AMK).\n *\n * **Key Lifecycle**:\n * 1. `active` - Current key used for encryption\n * 2. `rotating` - Transitional state during rotation\n * 3. `retired` - Old key kept for decryption of existing secrets\n * 4. `compromised` - Key marked as compromised, should not be used\n *\n * **Note**: This model is NOT tenant-scoped itself because it tracks\n * keys FOR tenants, not secrets owned BY tenants.\n *\n * @example\n * ```typescript\n * // Get active key for a tenant\n * const key = await tenantKeys.get({\n * tenantId: 'tenant-123',\n * status: 'active'\n * });\n *\n * // List all key versions for a tenant\n * const versions = await tenantKeys.list({\n * where: { tenantId: 'tenant-123' },\n * orderBy: 'version DESC'\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped({ mode: 'optional' })`):\n// `TenantKey` is deliberately NOT tenant-scoped — neither via the decorator nor via\n// `tenantScoped: true` on `@smrt()`. The row carries a `tenantId` column because each\n// TDEK belongs to a tenant, but the model itself must remain queryable across tenants\n// (e.g. cross-tenant key-rotation tooling, AMK rewrap jobs, super-admin auditing).\n// Adding the tenancy interceptor here would silently filter out keys the rotation\n// service needs to inspect. See `packages/secrets/CLAUDE.md` \"Known exceptions to\n// monorepo standards\" for the full rationale.\n@smrt({\n // Stores key material; never in the change feed (#2937).\n sensitive: true,\n // NOT tenant-scoped - this model tracks keys FOR tenants\n api: { include: [] }, // No API exposure\n mcp: { include: [] }, // No MCP exposure\n // CLI runs in-process for key-rotation tooling and audit; HTTP exposure is\n // intentionally excluded, so skipApiCheck acknowledges the divergence.\n cli: { include: ['list', 'get'], skipApiCheck: true },\n})\nexport class TenantKey extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-secrets\";\n /**\n * Tenant ID this key belongs to. Not tenant-scoped (see above), but the value\n * is a tenant id: uuid on Postgres, like every other tenant_id column.\n */\n @field({ sqlType: 'UUID' })\n tenantId: string = '';\n\n /**\n * Wrapped key data (format: wrappedKey:iv:authTag)\n */\n wrappedKey: string = '';\n\n /**\n * ID of the AMK used to wrap this key\n */\n amkKeyId: string = '';\n\n /**\n * Current status of the key\n */\n status: TenantKeyStatus = 'active';\n\n /**\n * Version number (increments on rotation)\n */\n version: number = 1;\n\n /**\n * Recommended rotation date\n */\n rotateAfter: Date | null = null;\n\n /**\n * When the key was retired (if applicable)\n */\n retiredAt: Date | null = null;\n\n constructor(options: TenantKeyOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.wrappedKey !== undefined) this.wrappedKey = options.wrappedKey;\n if (options.amkKeyId !== undefined) this.amkKeyId = options.amkKeyId;\n if (options.status !== undefined) this.status = options.status;\n if (options.version !== undefined) this.version = options.version;\n if (options.rotateAfter !== undefined) {\n this.rotateAfter =\n options.rotateAfter instanceof Date\n ? options.rotateAfter\n : options.rotateAfter\n ? new Date(options.rotateAfter)\n : null;\n }\n if (options.retiredAt !== undefined) {\n this.retiredAt =\n options.retiredAt instanceof Date\n ? options.retiredAt\n : options.retiredAt\n ? new Date(options.retiredAt)\n : null;\n }\n }\n\n /**\n * Check if this key is currently active\n */\n isActive(): boolean {\n return this.status === 'active';\n }\n\n /**\n * Check if this key needs rotation\n */\n needsRotation(): boolean {\n if (!this.rotateAfter) return false;\n return new Date() >= this.rotateAfter;\n }\n\n /**\n * Check if this key is retired\n */\n isRetired(): boolean {\n return this.status === 'retired';\n }\n\n /**\n * Check if this key is compromised\n */\n isCompromised(): boolean {\n return this.status === 'compromised';\n }\n\n /**\n * Check if this key can be used for decryption\n * (active or retired keys can decrypt)\n */\n canDecrypt(): boolean {\n return this.status === 'active' || this.status === 'retired';\n }\n\n /**\n * Check if this key can be used for encryption\n * (only active keys should encrypt)\n */\n canEncrypt(): boolean {\n return this.status === 'active';\n }\n\n /**\n * Mark this key as retired\n */\n retire(): void {\n this.status = 'retired';\n this.retiredAt = new Date();\n }\n\n /**\n * Mark this key as compromised\n */\n markCompromised(): void {\n this.status = 'compromised';\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TenantKey-ijZovCsO.js","names":[],"sources":["../../src/__smrt-register__.ts","../../src/models/SecretAuditLog.ts","../../src/models/Secret.ts","../../src/models/TenantKey.ts"],"sourcesContent":["// Generated by @happyvertical/smrt-core smrtPlugin at library build time.\n// The package manifest is inlined so self-registration cannot miss when a\n// downstream bundler relocates this module away from dist/manifest.json\n// (https://github.com/happyvertical/smrt/issues/1506,\n// https://github.com/happyvertical/smrt/issues/1507).\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\nObjectRegistry.registerPackageManifest(JSON.parse(\"{\\\"version\\\":\\\"1.0.0\\\",\\\"timestamp\\\":0,\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"packageVersion\\\":\\\"0.55.13\\\",\\\"objects\\\":{\\\"@happyvertical/smrt-secrets:SecretAuditLogCollection\\\":{\\\"name\\\":\\\"secretauditlogcollection\\\",\\\"className\\\":\\\"SecretAuditLogCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:SecretAuditLogCollection\\\",\\\"collection\\\":\\\"secretauditlogs\\\",\\\"description\\\":\\\"Collection for managing SecretAuditLog objects\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/collections/SecretAuditLogCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"listLogs\\\":{\\\"name\\\":\\\"listLogs\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"ListAuditLogsOptions\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SecretAuditLog[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getSecretHistory\\\":{\\\"name\\\":\\\"getSecretHistory\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"secretName\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"limit\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SecretAuditLog[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getUserActivity\\\":{\\\"name\\\":\\\"getUserActivity\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"userId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"limit\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SecretAuditLog[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getRecentFailures\\\":{\\\"name\\\":\\\"getRecentFailures\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"limit\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SecretAuditLog[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getRecentDenials\\\":{\\\"name\\\":\\\"getRecentDenials\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"limit\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SecretAuditLog[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"countByAction\\\":{\\\"name\\\":\\\"countByAction\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"since\\\",\\\"type\\\":\\\"Date\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<Record<SecretAuditAction, number>>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"countByResult\\\":{\\\"name\\\":\\\"countByResult\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"since\\\",\\\"type\\\":\\\"Date\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<Record<SecretAuditResult, number>>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"cleanup\\\":{\\\"name\\\":\\\"cleanup\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"olderThanDays\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<number>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"SecretAuditLog\\\",\\\"exportName\\\":\\\"SecretAuditLogCollection\\\",\\\"collectionExportName\\\":\\\"SecretAuditLogCollectionCollection\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"secret_audit_logs\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"secret_audit_logs\\\\\\\" (\\\\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,\\\\n \\\\\\\"secret_id\\\\\\\" UUID,\\\\n \\\\\\\"secret_name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"user_id\\\\\\\" UUID,\\\\n \\\\\\\"action\\\\\\\" TEXT DEFAULT 'read',\\\\n \\\\\\\"result\\\\\\\" TEXT DEFAULT 'success',\\\\n \\\\\\\"ip_address\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"user_agent\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"details\\\\\\\" JSON 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\\\":false,\\\"unique\\\":false},\\\"secret_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"secret_name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"user_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"action\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"read\\\"},\\\"result\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"success\\\"},\\\"ip_address\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"user_agent\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"details\\\":{\\\"type\\\":\\\"JSON\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":{}}},\\\"indexes\\\":[{\\\"name\\\":\\\"secret_audit_logs_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"secret_audit_logs_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"secret_audit_logs_secret_id_idx\\\",\\\"columns\\\":[\\\"secret_id\\\"]},{\\\"name\\\":\\\"secret_audit_logs_user_id_idx\\\",\\\"columns\\\":[\\\"user_id\\\"]}],\\\"version\\\":\\\"af0d679d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets\\\"},\\\"@happyvertical/smrt-secrets:SecretCollection\\\":{\\\"name\\\":\\\"secretcollection\\\",\\\"className\\\":\\\"SecretCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:SecretCollection\\\",\\\"collection\\\":\\\"secrets\\\",\\\"description\\\":\\\"Collection for managing Secret objects\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/collections/SecretCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"findByName\\\":{\\\"name\\\":\\\"findByName\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"name\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<Secret | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listSecrets\\\":{\\\"name\\\":\\\"listSecrets\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"ListSecretsOptions\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<Secret[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listActive\\\":{\\\"name\\\":\\\"listActive\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<Secret[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listByCategory\\\":{\\\"name\\\":\\\"listByCategory\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"category\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<Secret[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listExpiring\\\":{\\\"name\\\":\\\"listExpiring\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"daysAhead\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<Secret[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getCategories\\\":{\\\"name\\\":\\\"getCategories\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<string[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"countByStatus\\\":{\\\"name\\\":\\\"countByStatus\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<Record<SecretStatus, number>>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"deleteByName\\\":{\\\"name\\\":\\\"deleteByName\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"name\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<boolean>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"Secret\\\",\\\"exportName\\\":\\\"SecretCollection\\\",\\\"collectionExportName\\\":\\\"SecretCollectionCollection\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"secrets\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"secrets\\\\\\\" (\\\\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,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"description\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"category\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"encrypted_value\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"key_version\\\\\\\" INTEGER DEFAULT 1,\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"expires_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"last_accessed_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"access_count\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"metadata\\\\\\\" JSON 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\\\":false,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"description\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"category\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"encrypted_value\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"key_version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":1},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"expires_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"last_accessed_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"access_count\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"metadata\\\":{\\\"type\\\":\\\"JSON\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":{}}},\\\"indexes\\\":[{\\\"name\\\":\\\"secrets_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"secrets_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"6298a980\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets\\\"},\\\"@happyvertical/smrt-secrets:TenantKeyCollection\\\":{\\\"name\\\":\\\"tenantkeycollection\\\",\\\"className\\\":\\\"TenantKeyCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:TenantKeyCollection\\\",\\\"collection\\\":\\\"tenantkeys\\\",\\\"description\\\":\\\"Collection for managing TenantKey objects\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/collections/TenantKeyCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"getActiveKey\\\":{\\\"name\\\":\\\"getActiveKey\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantKey | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listKeyVersions\\\":{\\\"name\\\":\\\"listKeyVersions\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantKey[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getKeyVersion\\\":{\\\"name\\\":\\\"getKeyVersion\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"version\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantKey | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findKeysNeedingRotation\\\":{\\\"name\\\":\\\"findKeysNeedingRotation\\\",\\\"async\\\":true,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Promise<TenantKey[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listAllActiveKeys\\\":{\\\"name\\\":\\\"listAllActiveKeys\\\",\\\"async\\\":true,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Promise<TenantKey[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"countByStatus\\\":{\\\"name\\\":\\\"countByStatus\\\",\\\"async\\\":true,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Promise<Record<TenantKeyStatus, number>>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"markCompromised\\\":{\\\"name\\\":\\\"markCompromised\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"keyId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<boolean>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"cleanupRetiredKeys\\\":{\\\"name\\\":\\\"cleanupRetiredKeys\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"olderThanDays\\\",\\\"type\\\":\\\"number\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<number>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"TenantKey\\\",\\\"exportName\\\":\\\"TenantKeyCollection\\\",\\\"collectionExportName\\\":\\\"TenantKeyCollectionCollection\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"tenant_keys\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"tenant_keys\\\\\\\" (\\\\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,\\\\n \\\\\\\"wrapped_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"amk_key_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"version\\\\\\\" INTEGER DEFAULT 1,\\\\n \\\\\\\"rotate_after\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"retired_at\\\\\\\" TIMESTAMP\\\\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\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"wrapped_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"amk_key_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":1},\\\"rotate_after\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"retired_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"tenant_keys_tenant_id_slug_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"tenant_keys_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]}],\\\"version\\\":\\\"abc3474a\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets\\\"},\\\"@happyvertical/smrt-secrets:Secret\\\":{\\\"name\\\":\\\"secret\\\",\\\"className\\\":\\\"Secret\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:Secret\\\",\\\"collection\\\":\\\"secrets\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/models/Secret.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"autoFilter\\\":true,\\\"autoPopulate\\\":true,\\\"allowSuperAdminBypass\\\":false}}},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"description\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"category\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"encryptedValue\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"keyVersion\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":1},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"active\\\",\\\"enum\\\":[\\\"active\\\",\\\"disabled\\\",\\\"expired\\\"]},\\\"expiresAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"lastAccessedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"accessCount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"metadata\\\":{\\\"type\\\":\\\"json\\\",\\\"required\\\":false,\\\"default\\\":{}}},\\\"methods\\\":{\\\"isActive\\\":{\\\"name\\\":\\\"isActive\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isExpired\\\":{\\\"name\\\":\\\"isExpired\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isUsable\\\":{\\\"name\\\":\\\"isUsable\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"recordAccess\\\":{\\\"name\\\":\\\"recordAccess\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"disable\\\":{\\\"name\\\":\\\"disable\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"enable\\\":{\\\"name\\\":\\\"enable\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"sensitive\\\":true,\\\"tenantScoped\\\":true,\\\"api\\\":{\\\"include\\\":[]},\\\"mcp\\\":{\\\"include\\\":[]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\"],\\\"skipApiCheck\\\":true},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"Secret\\\",\\\"collectionExportName\\\":\\\"SecretCollection\\\",\\\"displayLabelField\\\":\\\"name\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"secrets\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"secrets\\\\\\\" (\\\\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,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"description\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"category\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"encrypted_value\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"key_version\\\\\\\" INTEGER DEFAULT 1,\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"expires_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"last_accessed_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"access_count\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"metadata\\\\\\\" JSON 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\\\":false,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"description\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"category\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"encrypted_value\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"key_version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":1},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"expires_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"last_accessed_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"access_count\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"metadata\\\":{\\\"type\\\":\\\"JSON\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":{}}},\\\"indexes\\\":[{\\\"name\\\":\\\"secrets_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"secrets_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"6298a980\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets/models\\\"},\\\"@happyvertical/smrt-secrets:SecretAuditLog\\\":{\\\"name\\\":\\\"secretauditlog\\\",\\\"className\\\":\\\"SecretAuditLog\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:SecretAuditLog\\\",\\\"collection\\\":\\\"secretauditlogs\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/models/SecretAuditLog.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"autoFilter\\\":true,\\\"autoPopulate\\\":true,\\\"allowSuperAdminBypass\\\":false}}},\\\"secretId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"Secret\\\",\\\"_meta\\\":{\\\"constraint\\\":false}},\\\"secretName\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"userId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":false,\\\"related\\\":\\\"@happyvertical/smrt-users:User\\\"},\\\"action\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"read\\\",\\\"enum\\\":[\\\"create\\\",\\\"read\\\",\\\"update\\\",\\\"delete\\\",\\\"rotate_key\\\",\\\"disable\\\",\\\"enable\\\",\\\"expire\\\"]},\\\"result\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"success\\\",\\\"enum\\\":[\\\"success\\\",\\\"failure\\\",\\\"denied\\\"]},\\\"ipAddress\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"userAgent\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"details\\\":{\\\"type\\\":\\\"json\\\",\\\"required\\\":false,\\\"default\\\":{}}},\\\"methods\\\":{\\\"isSuccess\\\":{\\\"name\\\":\\\"isSuccess\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isFailure\\\":{\\\"name\\\":\\\"isFailure\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isDenied\\\":{\\\"name\\\":\\\"isDenied\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isReadAction\\\":{\\\"name\\\":\\\"isReadAction\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isWriteAction\\\":{\\\"name\\\":\\\"isWriteAction\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isKeyOperation\\\":{\\\"name\\\":\\\"isKeyOperation\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tenantScoped\\\":true,\\\"api\\\":{\\\"include\\\":[]},\\\"mcp\\\":{\\\"include\\\":[]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\"],\\\"skipApiCheck\\\":true},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"SecretAuditLog\\\",\\\"collectionExportName\\\":\\\"SecretAuditLogCollection\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"secret_audit_logs\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"secret_audit_logs\\\\\\\" (\\\\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,\\\\n \\\\\\\"secret_id\\\\\\\" UUID,\\\\n \\\\\\\"secret_name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"user_id\\\\\\\" UUID,\\\\n \\\\\\\"action\\\\\\\" TEXT DEFAULT 'read',\\\\n \\\\\\\"result\\\\\\\" TEXT DEFAULT 'success',\\\\n \\\\\\\"ip_address\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"user_agent\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"details\\\\\\\" JSON 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\\\":false,\\\"unique\\\":false},\\\"secret_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"secret_name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"user_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"action\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"read\\\"},\\\"result\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"success\\\"},\\\"ip_address\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"user_agent\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"details\\\":{\\\"type\\\":\\\"JSON\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":{}}},\\\"indexes\\\":[{\\\"name\\\":\\\"secret_audit_logs_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"secret_audit_logs_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"secret_audit_logs_secret_id_idx\\\",\\\"columns\\\":[\\\"secret_id\\\"]},{\\\"name\\\":\\\"secret_audit_logs_user_id_idx\\\",\\\"columns\\\":[\\\"user_id\\\"]}],\\\"version\\\":\\\"af0d679d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets/models\\\"},\\\"@happyvertical/smrt-secrets:TenantKey\\\":{\\\"name\\\":\\\"tenantkey\\\",\\\"className\\\":\\\"TenantKey\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-secrets:TenantKey\\\",\\\"collection\\\":\\\"tenantkeys\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/secrets/src/models/TenantKey.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-secrets\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\"}},\\\"wrappedKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"amkKeyId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"active\\\",\\\"enum\\\":[\\\"active\\\",\\\"rotating\\\",\\\"retired\\\",\\\"compromised\\\"]},\\\"version\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":1},\\\"rotateAfter\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"retiredAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false}},\\\"methods\\\":{\\\"isActive\\\":{\\\"name\\\":\\\"isActive\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"needsRotation\\\":{\\\"name\\\":\\\"needsRotation\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isRetired\\\":{\\\"name\\\":\\\"isRetired\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isCompromised\\\":{\\\"name\\\":\\\"isCompromised\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"canDecrypt\\\":{\\\"name\\\":\\\"canDecrypt\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"canEncrypt\\\":{\\\"name\\\":\\\"canEncrypt\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"retire\\\":{\\\"name\\\":\\\"retire\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"markCompromised\\\":{\\\"name\\\":\\\"markCompromised\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"sensitive\\\":true,\\\"api\\\":{\\\"include\\\":[]},\\\"mcp\\\":{\\\"include\\\":[]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"],\\\"skipApiCheck\\\":true},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"TenantKey\\\",\\\"collectionExportName\\\":\\\"TenantKeyCollection\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"tenant_keys\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"tenant_keys\\\\\\\" (\\\\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,\\\\n \\\\\\\"wrapped_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"amk_key_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"version\\\\\\\" INTEGER DEFAULT 1,\\\\n \\\\\\\"rotate_after\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"retired_at\\\\\\\" TIMESTAMP\\\\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\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"wrapped_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"amk_key_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":1},\\\"rotate_after\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"retired_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"tenant_keys_tenant_id_slug_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"tenant_keys_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]}],\\\"version\\\":\\\"abc3474a\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-secrets/models\\\"}},\\\"moduleType\\\":\\\"smrt\\\",\\\"smrtDependencies\\\":[\\\"@happyvertical/smrt-core\\\",\\\"@happyvertical/smrt-tenancy\\\"],\\\"browser\\\":{\\\"status\\\":\\\"server-only\\\",\\\"issues\\\":[\\\"#3624\\\",\\\"#3627\\\"],\\\"reason\\\":\\\"@happyvertical/secrets (node:child_process, node:crypto) and sql\\\",\\\"via\\\":[\\\"@happyvertical/smrt-tenancy\\\"]},\\\"stampsConstructors\\\":true}\"));\n","/**\n * SecretAuditLog model - Audit trail for secret operations\n * @packageDocumentation\n */\n\nimport type {\n SmrtCreateInput,\n SmrtObjectOptions,\n} from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\n\n/**\n * Secret audit action types\n */\nexport type SecretAuditAction =\n | 'create'\n | 'read'\n | 'update'\n | 'delete'\n | 'rotate_key'\n | 'disable'\n | 'enable'\n | 'expire';\n\n/**\n * Audit result types\n */\nexport type SecretAuditResult = 'success' | 'failure' | 'denied';\n\n/**\n * Constructor options for {@link SecretAuditLog}. Each field is optional and\n * mirrors a persisted column.\n */\nexport interface SecretAuditLogOptions extends SmrtObjectOptions {\n tenantId?: string | null;\n secretId?: string | null;\n secretName?: string;\n userId?: string | null;\n action?: SecretAuditAction;\n result?: SecretAuditResult;\n ipAddress?: string;\n userAgent?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * SecretAuditLog records all operations on secrets for compliance\n * and security monitoring.\n *\n * Every secret operation (create, read, update, delete, key rotation)\n * is logged with the user, action, result, and relevant details.\n *\n * **Retention**: Audit logs should be retained according to your\n * compliance requirements (typically 1-7 years).\n *\n * @example\n * ```typescript\n * // Query recent audit logs\n * const logs = await auditLogs.list({\n * where: { tenantId: 'tenant-123' },\n * orderBy: 'created_at DESC',\n * limit: 100\n * });\n *\n * // Filter by action\n * const reads = await auditLogs.list({\n * where: {\n * tenantId: 'tenant-123',\n * action: 'read'\n * }\n * });\n *\n * // Filter by secret name\n * const apiKeyLogs = await auditLogs.list({\n * where: {\n * tenantId: 'tenant-123',\n * secretName: 'stripe-api-key'\n * }\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped({ mode: 'optional' })`):\n// `SecretAuditLog` uses the inline `tenantScoped: true` form on `@smrt()` rather than\n// the dedicated `@TenantScoped` decorator. Audit-trail queries are read-mostly and run\n// in mixed contexts — under a tenant for tenant-scoped reports, and (prospectively)\n// under super-admin bypass for compliance review. Cross-tenant audit queries should\n// be wrapped in `withSuperAdminBypass()` from `@happyvertical/smrt-tenancy` at the\n// call site, and the bypass only applies once this model opts in with\n// `allowSuperAdminBypass: true` (smrt#2973; it does not today, so cross-tenant\n// compliance reads use `withSystemContext()` instead); this package has no such call sites today, so the pattern is\n// prescriptive guidance for compliance tooling rather than current practice. See\n// `packages/secrets/CLAUDE.md` \"Known exceptions to monorepo standards\" for context.\n@smrt({\n tenantScoped: true,\n api: { include: [] }, // No API exposure\n mcp: { include: [] }, // No MCP exposure\n // CLI runs in-process for compliance review; HTTP exposure is intentionally\n // excluded, so skipApiCheck acknowledges the cli.include / api.include divergence.\n cli: { include: ['list'], skipApiCheck: true },\n})\nexport class SecretAuditLog extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-secrets\";\n /**\n * Tenant associated with the audited secret operation.\n */\n tenantId: string | null = null;\n\n /**\n * ID of the secret (may identify a secret that has since been deleted).\n *\n * Compliance audit rows intentionally outlive their source secret, so this\n * remains an app-side relationship without a physical database constraint.\n */\n @foreignKey('Secret', { constraint: false })\n secretId: string | null = null;\n\n /**\n * Name of the secret at the time of the operation\n */\n secretName: string = '';\n\n /**\n * ID of the user who performed the action, or `null` for system-initiated\n * operations with no authenticated user. Stored as a native `uuid` column on\n * Postgres, so a non-UUID actor sentinel must never reach it —\n * {@link createAuditEntry} normalizes the `'system'` sentinel to null (#1444).\n */\n @crossPackageRef('@happyvertical/smrt-users:User')\n userId: string | null = null;\n\n /**\n * The action that was performed\n */\n action: SecretAuditAction = 'read';\n\n /**\n * Result of the operation\n */\n result: SecretAuditResult = 'success';\n\n /**\n * IP address of the client (if available)\n */\n ipAddress: string = '';\n\n /**\n * User agent string (if available)\n */\n userAgent: string = '';\n\n /**\n * Additional context about the operation\n */\n details: Record<string, unknown> = {};\n\n constructor(options: SecretAuditLogOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) {\n this.tenantId = options.tenantId;\n }\n if (options.secretId !== undefined) this.secretId = options.secretId;\n if (options.secretName !== undefined) this.secretName = options.secretName;\n if (options.userId !== undefined) this.userId = options.userId;\n if (options.action !== undefined) this.action = options.action;\n if (options.result !== undefined) this.result = options.result;\n if (options.ipAddress !== undefined) this.ipAddress = options.ipAddress;\n if (options.userAgent !== undefined) this.userAgent = options.userAgent;\n if (options.details !== undefined) this.details = options.details;\n }\n\n /**\n * Check if this was a successful operation\n */\n isSuccess(): boolean {\n return this.result === 'success';\n }\n\n /**\n * Check if this was a failed operation\n */\n isFailure(): boolean {\n return this.result === 'failure';\n }\n\n /**\n * Check if this was a denied operation (permission denied)\n */\n isDenied(): boolean {\n return this.result === 'denied';\n }\n\n /**\n * Check if this is a read operation\n */\n isReadAction(): boolean {\n return this.action === 'read';\n }\n\n /**\n * Check if this is a write operation (create, update, delete)\n */\n isWriteAction(): boolean {\n return ['create', 'update', 'delete'].includes(this.action);\n }\n\n /**\n * Check if this is a key operation\n */\n isKeyOperation(): boolean {\n return this.action === 'rotate_key';\n }\n}\n\nconst UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Create an audit log entry for a secret operation\n */\nexport function createAuditEntry(params: {\n secretId?: string | null;\n secretName: string;\n tenantId?: string | null;\n userId?: string | null;\n action: SecretAuditAction;\n result: SecretAuditResult;\n ipAddress?: string;\n userAgent?: string;\n details?: Record<string, unknown>;\n}): SmrtCreateInput<SecretAuditLog> {\n const tenantId =\n params.tenantId === undefined || params.tenantId === 'system'\n ? null\n : params.tenantId;\n\n // The `userId` column is a native `uuid` on Postgres. A missing actor and the\n // `'system'`/empty sentinels are not valid UUIDs, so normalize them all to\n // null — a system-initiated operation has no authenticated user. Callers may\n // pass `null`/`undefined` directly to express that (#1444).\n // Any other value that is not a uuid (an email-login identity, a service\n // name) would fail the insert and with it the audited operation; record it\n // in `details.actorId` instead so the actor is never lost.\n const rawUserId =\n params.userId == null || params.userId === 'system' || params.userId === ''\n ? null\n : params.userId;\n const userId =\n rawUserId !== null && UUID_PATTERN.test(rawUserId) ? rawUserId : null;\n const details =\n rawUserId !== null && userId === null\n ? { ...(params.details ?? {}), actorId: rawUserId }\n : (params.details ?? {});\n\n const entry: SmrtCreateInput<SecretAuditLog> = {\n secretId: params.secretId ?? null,\n secretName: params.secretName,\n userId,\n action: params.action,\n result: params.result,\n ipAddress: params.ipAddress ?? '',\n userAgent: params.userAgent ?? '',\n details,\n tenantId,\n };\n return entry;\n}\n","/**\n * Secret model - Tenant-scoped encrypted secrets storage\n * @packageDocumentation\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { SmrtObject, smrt } from '@happyvertical/smrt-core';\n\n/**\n * Secret status values\n */\nexport type SecretStatus = 'active' | 'disabled' | 'expired';\n\n/**\n * Constructor options for {@link Secret}. Each field is optional and mirrors a\n * persisted column; date fields also accept the serialized forms accepted by\n * `new Date()` so hydrated rows coerce cleanly.\n */\nexport interface SecretOptions extends SmrtObjectOptions {\n tenantId?: string;\n name?: string;\n description?: string;\n category?: string;\n encryptedValue?: string;\n keyVersion?: number;\n status?: SecretStatus;\n expiresAt?: Date | string | number | null;\n lastAccessedAt?: Date | string | number | null;\n accessCount?: number;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Secret represents an encrypted value stored per-tenant.\n *\n * Secrets are tenant-scoped and use envelope encryption:\n * - Each tenant has their own Data Encryption Key (TDEK)\n * - The TDEK is wrapped by the Application Master Key (AMK)\n * - Secret values are encrypted by the unwrapped TDEK\n *\n * **Security**: This model deliberately excludes API and MCP exposure\n * to prevent accidental secret leakage. Secrets are only accessible\n * via CLI commands or direct service calls.\n *\n * @example\n * ```typescript\n * import { SecretService } from '@happyvertical/smrt-secrets';\n *\n * const service = await SecretService.create({ db });\n *\n * await withTenant({ tenantId: 'tenant-123' }, async () => {\n * // Store a secret\n * await service.store('api-key', 'sk_live_xxx', { category: 'stripe' });\n *\n * // Retrieve (auto-decrypts)\n * const apiKey = await service.retrieve('api-key');\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped({ mode: 'optional' })`):\n// `Secret` uses the inline `tenantScoped: true` form on `@smrt()` rather than the\n// dedicated `@TenantScoped` decorator from `@happyvertical/smrt-tenancy`. The boolean\n// form gives us required-mode tenant scoping without depending on the tenancy package\n// at the model layer, while `SecretService` performs manual scoping by setting\n// `context = tenantId` on each row. The `(slug, context)` upsert key derived from the\n// base `SmrtObject` fields is what gives different tenants isolated namespaces for\n// secret names — switching to the decorator without changing the upsert key would\n// surface false-positive name collisions across tenants. See\n// `packages/secrets/CLAUDE.md` \"Known exceptions to monorepo standards\" for context.\n@smrt({\n // Stores key material; never in the change feed (#2937).\n sensitive: true,\n tenantScoped: true,\n // NO API or MCP exposure for security\n api: { include: [] },\n mcp: { include: [] },\n // CLI runs in-process; secrets must never be reachable over HTTP, so\n // skipApiCheck acknowledges the cli.include / api.include divergence.\n cli: { include: ['list'], skipApiCheck: true }, // Only list names, not values\n})\nexport class Secret extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-secrets\";\n /**\n * Tenant that owns this secret. Also stored in context for per-tenant name uniqueness.\n */\n tenantId: string = '';\n\n /**\n * Unique name for the secret within the tenant\n */\n name: string = '';\n\n /**\n * Human-readable description\n */\n description: string = '';\n\n /**\n * Category for organization (e.g., 'database', 'api-key', 'oauth')\n */\n category: string = '';\n\n /**\n * JSON-encoded EncryptedEnvelope from @happyvertical/secrets\n */\n encryptedValue: string = '';\n\n /**\n * Version of the tenant key used to encrypt this secret\n */\n keyVersion: number = 1;\n\n /**\n * Current status of the secret\n */\n status: SecretStatus = 'active';\n\n /**\n * Optional expiration date\n */\n expiresAt: Date | null = null;\n\n /**\n * Last time this secret was accessed (decrypted)\n */\n lastAccessedAt: Date | null = null;\n\n /**\n * Number of times this secret has been accessed\n */\n accessCount: number = 0;\n\n /**\n * Additional metadata stored with the secret\n */\n metadata: Record<string, unknown> = {};\n\n constructor(options: SecretOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.name !== undefined) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.category !== undefined) this.category = options.category;\n if (options.encryptedValue !== undefined)\n this.encryptedValue = options.encryptedValue;\n if (options.keyVersion !== undefined) this.keyVersion = options.keyVersion;\n if (options.status !== undefined) this.status = options.status;\n if (options.expiresAt !== undefined) {\n this.expiresAt =\n options.expiresAt instanceof Date\n ? options.expiresAt\n : options.expiresAt\n ? new Date(options.expiresAt)\n : null;\n }\n if (options.lastAccessedAt !== undefined) {\n this.lastAccessedAt =\n options.lastAccessedAt instanceof Date\n ? options.lastAccessedAt\n : options.lastAccessedAt\n ? new Date(options.lastAccessedAt)\n : null;\n }\n if (options.accessCount !== undefined)\n this.accessCount = options.accessCount;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n /**\n * Check if the secret is currently active\n */\n isActive(): boolean {\n return this.status === 'active';\n }\n\n /**\n * Check if the secret has expired\n */\n isExpired(): boolean {\n if (!this.expiresAt) return false;\n return new Date() >= this.expiresAt;\n }\n\n /**\n * Check if the secret can be used (active and not expired)\n */\n isUsable(): boolean {\n return this.isActive() && !this.isExpired();\n }\n\n /**\n * Record an access to this secret\n */\n recordAccess(): void {\n this.lastAccessedAt = new Date();\n this.accessCount += 1;\n }\n\n /**\n * Disable the secret\n */\n disable(): void {\n this.status = 'disabled';\n }\n\n /**\n * Enable the secret\n */\n enable(): void {\n this.status = 'active';\n }\n}\n","/**\n * TenantKey model - Tracks per-tenant Data Encryption Keys (TDEKs)\n * @packageDocumentation\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\n\n/**\n * Key status values\n */\nexport type TenantKeyStatus = 'active' | 'rotating' | 'retired' | 'compromised';\n\n/**\n * Constructor options for {@link TenantKey}. Each field is optional and mirrors\n * a persisted column; date fields also accept the serialized forms accepted by\n * `new Date()` so hydrated rows coerce cleanly.\n */\nexport interface TenantKeyOptions extends SmrtObjectOptions {\n tenantId?: string;\n wrappedKey?: string;\n amkKeyId?: string;\n status?: TenantKeyStatus;\n version?: number;\n rotateAfter?: Date | string | number | null;\n retiredAt?: Date | string | number | null;\n}\n\n/**\n * TenantKey tracks the per-tenant Data Encryption Keys (TDEKs).\n *\n * Each tenant has one or more TDEKs stored in wrapped form. The wrapped key\n * can only be decrypted using the Application Master Key (AMK).\n *\n * **Key Lifecycle**:\n * 1. `active` - Current key used for encryption\n * 2. `rotating` - Transitional state during rotation\n * 3. `retired` - Old key kept for decryption of existing secrets\n * 4. `compromised` - Key marked as compromised, should not be used\n *\n * **Note**: This model is NOT tenant-scoped itself because it tracks\n * keys FOR tenants, not secrets owned BY tenants.\n *\n * @example\n * ```typescript\n * // Get active key for a tenant\n * const key = await tenantKeys.get({\n * tenantId: 'tenant-123',\n * status: 'active'\n * });\n *\n * // List all key versions for a tenant\n * const versions = await tenantKeys.list({\n * where: { tenantId: 'tenant-123' },\n * orderBy: 'version DESC'\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped({ mode: 'optional' })`):\n// `TenantKey` is deliberately NOT tenant-scoped — neither via the decorator nor via\n// `tenantScoped: true` on `@smrt()`. The row carries a `tenantId` column because each\n// TDEK belongs to a tenant, but the model itself must remain queryable across tenants\n// (e.g. cross-tenant key-rotation tooling, AMK rewrap jobs, super-admin auditing).\n// Adding the tenancy interceptor here would silently filter out keys the rotation\n// service needs to inspect. See `packages/secrets/CLAUDE.md` \"Known exceptions to\n// monorepo standards\" for the full rationale.\n@smrt({\n // Stores key material; never in the change feed (#2937).\n sensitive: true,\n // NOT tenant-scoped - this model tracks keys FOR tenants\n api: { include: [] }, // No API exposure\n mcp: { include: [] }, // No MCP exposure\n // CLI runs in-process for key-rotation tooling and audit; HTTP exposure is\n // intentionally excluded, so skipApiCheck acknowledges the divergence.\n cli: { include: ['list', 'get'], skipApiCheck: true },\n})\nexport class TenantKey extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-secrets\";\n /**\n * Tenant ID this key belongs to. Not tenant-scoped (see above), but the value\n * is a tenant id: uuid on Postgres, like every other tenant_id column.\n */\n @field({ sqlType: 'UUID' })\n tenantId: string = '';\n\n /**\n * Wrapped key data (format: wrappedKey:iv:authTag)\n */\n wrappedKey: string = '';\n\n /**\n * ID of the AMK used to wrap this key\n */\n amkKeyId: string = '';\n\n /**\n * Current status of the key\n */\n status: TenantKeyStatus = 'active';\n\n /**\n * Version number (increments on rotation)\n */\n version: number = 1;\n\n /**\n * Recommended rotation date\n */\n rotateAfter: Date | null = null;\n\n /**\n * When the key was retired (if applicable)\n */\n retiredAt: Date | null = null;\n\n constructor(options: TenantKeyOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.wrappedKey !== undefined) this.wrappedKey = options.wrappedKey;\n if (options.amkKeyId !== undefined) this.amkKeyId = options.amkKeyId;\n if (options.status !== undefined) this.status = options.status;\n if (options.version !== undefined) this.version = options.version;\n if (options.rotateAfter !== undefined) {\n this.rotateAfter =\n options.rotateAfter instanceof Date\n ? options.rotateAfter\n : options.rotateAfter\n ? new Date(options.rotateAfter)\n : null;\n }\n if (options.retiredAt !== undefined) {\n this.retiredAt =\n options.retiredAt instanceof Date\n ? options.retiredAt\n : options.retiredAt\n ? new Date(options.retiredAt)\n : null;\n }\n }\n\n /**\n * Check if this key is currently active\n */\n isActive(): boolean {\n return this.status === 'active';\n }\n\n /**\n * Check if this key needs rotation\n */\n needsRotation(): boolean {\n if (!this.rotateAfter) return false;\n return new Date() >= this.rotateAfter;\n }\n\n /**\n * Check if this key is retired\n */\n isRetired(): boolean {\n return this.status === 'retired';\n }\n\n /**\n * Check if this key is compromised\n */\n isCompromised(): boolean {\n return this.status === 'compromised';\n }\n\n /**\n * Check if this key can be used for decryption\n * (active or retired keys can decrypt)\n */\n canDecrypt(): boolean {\n return this.status === 'active' || this.status === 'retired';\n }\n\n /**\n * Check if this key can be used for encryption\n * (only active keys should encrypt)\n */\n canEncrypt(): boolean {\n return this.status === 'active';\n }\n\n /**\n * Mark this key as retired\n */\n retire(): void {\n this.status = 'retired';\n this.retiredAt = new Date();\n }\n\n /**\n * Mark this key as compromised\n */\n markCompromised(): void {\n this.status = 'compromised';\n }\n}\n"],"mappings":"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"}
|
|
@@ -13,7 +13,9 @@ export interface ListAuditLogsOptions {
|
|
|
13
13
|
* (e.g. SecretService.getAuditLogs) must always set this — audit rows
|
|
14
14
|
* reference secret names and must not leak across tenants (issue #1501).
|
|
15
15
|
* Omit only for cross-tenant compliance tooling running under
|
|
16
|
-
* withSuperAdminBypass()
|
|
16
|
+
* withSystemContext(); withSuperAdminBypass() does not lift tenant
|
|
17
|
+
* filtering here because SecretAuditLog does not declare
|
|
18
|
+
* allowSuperAdminBypass (smrt#2973).
|
|
17
19
|
*/
|
|
18
20
|
tenantId?: string;
|
|
19
21
|
/** Filter by secret name */
|
|
@@ -47,7 +49,8 @@ export declare class SecretAuditLogCollection extends SmrtCollection<SecretAudit
|
|
|
47
49
|
*
|
|
48
50
|
* @param tenantId - Scope to this tenant's audit trail, or `null` for a
|
|
49
51
|
* cross-tenant compliance query (which must run under
|
|
50
|
-
* `
|
|
52
|
+
* `withSystemContext()` from `@happyvertical/smrt-tenancy`; super-admin
|
|
53
|
+
* bypass does not apply to this model, smrt#2973). Audit rows
|
|
51
54
|
* reference secret names and must not leak across tenants (#1503).
|
|
52
55
|
*/
|
|
53
56
|
getSecretHistory(tenantId: string | null, secretName: string, limit?: number): Promise<SecretAuditLog[]>;
|
|
@@ -55,35 +58,40 @@ export declare class SecretAuditLogCollection extends SmrtCollection<SecretAudit
|
|
|
55
58
|
* Get audit logs for a specific user.
|
|
56
59
|
*
|
|
57
60
|
* @param tenantId - Scope to this tenant's audit trail, or `null` for a
|
|
58
|
-
* cross-tenant compliance query under `
|
|
61
|
+
* cross-tenant compliance query under `withSystemContext()`
|
|
62
|
+
* (#1503; super-admin bypass does not apply, smrt#2973).
|
|
59
63
|
*/
|
|
60
64
|
getUserActivity(tenantId: string | null, userId: string, limit?: number): Promise<SecretAuditLog[]>;
|
|
61
65
|
/**
|
|
62
66
|
* Get recent failures.
|
|
63
67
|
*
|
|
64
68
|
* @param tenantId - Scope to this tenant's audit trail, or `null` for a
|
|
65
|
-
* cross-tenant compliance query under `
|
|
69
|
+
* cross-tenant compliance query under `withSystemContext()`
|
|
70
|
+
* (#1503; super-admin bypass does not apply, smrt#2973).
|
|
66
71
|
*/
|
|
67
72
|
getRecentFailures(tenantId: string | null, limit?: number): Promise<SecretAuditLog[]>;
|
|
68
73
|
/**
|
|
69
74
|
* Get recent denied access attempts.
|
|
70
75
|
*
|
|
71
76
|
* @param tenantId - Scope to this tenant's audit trail, or `null` for a
|
|
72
|
-
* cross-tenant compliance query under `
|
|
77
|
+
* cross-tenant compliance query under `withSystemContext()`
|
|
78
|
+
* (#1503; super-admin bypass does not apply, smrt#2973).
|
|
73
79
|
*/
|
|
74
80
|
getRecentDenials(tenantId: string | null, limit?: number): Promise<SecretAuditLog[]>;
|
|
75
81
|
/**
|
|
76
82
|
* Count operations by action type.
|
|
77
83
|
*
|
|
78
84
|
* @param tenantId - Scope to this tenant's audit trail, or `null` for a
|
|
79
|
-
* cross-tenant compliance count under `
|
|
85
|
+
* cross-tenant compliance count under `withSystemContext()`
|
|
86
|
+
* (#1503; super-admin bypass does not apply, smrt#2973).
|
|
80
87
|
*/
|
|
81
88
|
countByAction(tenantId: string | null, since?: Date): Promise<Record<SecretAuditAction, number>>;
|
|
82
89
|
/**
|
|
83
90
|
* Count operations by result.
|
|
84
91
|
*
|
|
85
92
|
* @param tenantId - Scope to this tenant's audit trail, or `null` for a
|
|
86
|
-
* cross-tenant compliance count under `
|
|
93
|
+
* cross-tenant compliance count under `withSystemContext()`
|
|
94
|
+
* (#1503; super-admin bypass does not apply, smrt#2973).
|
|
87
95
|
*/
|
|
88
96
|
countByResult(tenantId: string | null, since?: Date): Promise<Record<SecretAuditResult, number>>;
|
|
89
97
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecretAuditLogCollection.d.ts","sourceRoot":"","sources":["../../src/collections/SecretAuditLogCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EACL,KAAK,iBAAiB,EACtB,cAAc,EACd,KAAK,iBAAiB,EACvB,MAAM,6BAA6B,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC
|
|
1
|
+
{"version":3,"file":"SecretAuditLogCollection.d.ts","sourceRoot":"","sources":["../../src/collections/SecretAuditLogCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EACL,KAAK,iBAAiB,EACtB,cAAc,EACd,KAAK,iBAAiB,EACvB,MAAM,6BAA6B,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,uBAAuB;IACvB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,iCAAiC;IACjC,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,+BAA+B;IAC/B,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC1E,MAAM,CAAC,QAAQ,CAAC,UAAU,wBAAkB;IAE5C;;OAEG;IACG,QAAQ,CACZ,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,cAAc,EAAE,CAAC;IAuC5B;;;;;;;;OAQG;IACG,gBAAgB,CACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,cAAc,EAAE,CAAC;IAQ5B;;;;;;OAMG;IACG,eAAe,CACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,cAAc,EAAE,CAAC;IAI5B;;;;;;OAMG;IACG,iBAAiB,CACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,cAAc,EAAE,CAAC;IAQ5B;;;;;;OAMG;IACG,gBAAgB,CACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,cAAc,EAAE,CAAC;IAQ5B;;;;;;OAMG;IACG,aAAa,CACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,KAAK,CAAC,EAAE,IAAI,GACX,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAyB7C;;;;;;OAMG;IACG,aAAa,CACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,KAAK,CAAC,EAAE,IAAI,GACX,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAoB7C;;;OAGG;IACG,OAAO,CAAC,aAAa,GAAE,MAAY,GAAG,OAAO,CAAC,MAAM,CAAC;CAkB5D"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as createAuditEntry, n as Secret, r as SecretAuditLog, t as TenantKey } from "./chunks/TenantKey-
|
|
2
|
-
import { a as SecretAuditLogCollection, i as SecretCollection, n as SecretService, r as TenantKeyCollection, t as SecretKeyDriftError } from "./chunks/SecretService-
|
|
1
|
+
import { i as createAuditEntry, n as Secret, r as SecretAuditLog, t as TenantKey } from "./chunks/TenantKey-ijZovCsO.js";
|
|
2
|
+
import { a as SecretAuditLogCollection, i as SecretCollection, n as SecretService, r as TenantKeyCollection, t as SecretKeyDriftError } from "./chunks/SecretService-3iOtNnBI.js";
|
|
3
3
|
import { AMKUnavailableError, DecryptionError, EncryptionError, InvalidKeyFormatError, KeyNotFoundError, KeyRotationError, SecretError, StoreNotInitializedError, TenantKeyMissingError } from "@happyvertical/secrets";
|
|
4
4
|
//#region src/index.ts
|
|
5
5
|
/** @internal */
|
package/dist/manifest.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecretAuditLog.d.ts","sourceRoot":"","sources":["../../src/models/SecretAuditLog.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEjE;;;GAGG;AACH,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;
|
|
1
|
+
{"version":3,"file":"SecretAuditLog.d.ts","sourceRoot":"","sources":["../../src/models/SecretAuditLog.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEjE;;;GAGG;AACH,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAYH,qBAQa,cAAe,SAAQ,UAAU;IAC5C;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;;;;OAKG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAM;IAExB;;;;;OAKG;IAEH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE7B;;OAEG;IACH,MAAM,EAAE,iBAAiB,CAAU;IAEnC;;OAEG;IACH,MAAM,EAAE,iBAAiB,CAAa;IAEtC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM;gBAE1B,OAAO,GAAE,qBAA0B;IAe/C;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,cAAc,IAAI,OAAO;CAG1B;AAKD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,GAAG,eAAe,CAAC,cAAc,CAAC,CAoClC"}
|
package/dist/models/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as createAuditEntry, n as Secret, r as SecretAuditLog, t as TenantKey } from "../chunks/TenantKey-
|
|
1
|
+
import { i as createAuditEntry, n as Secret, r as SecretAuditLog, t as TenantKey } from "../chunks/TenantKey-ijZovCsO.js";
|
|
2
2
|
export { Secret, SecretAuditLog, TenantKey, createAuditEntry };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as SecretService, t as SecretKeyDriftError } from "../chunks/SecretService-
|
|
1
|
+
import { n as SecretService, t as SecretKeyDriftError } from "../chunks/SecretService-3iOtNnBI.js";
|
|
2
2
|
export { SecretKeyDriftError, SecretService };
|
package/dist/smrt-knowledge.json
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
"sensitiveFieldsExcluded": true,
|
|
4
4
|
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
5
5
|
"packageName": "@happyvertical/smrt-secrets",
|
|
6
|
-
"packageVersion": "0.55.
|
|
6
|
+
"packageVersion": "0.55.13",
|
|
7
7
|
"sourceManifestPath": "dist/manifest.json",
|
|
8
8
|
"agentDocPath": "AGENTS.md",
|
|
9
9
|
"sourceHashes": {
|
|
10
|
-
"manifest": "
|
|
11
|
-
"packageJson": "
|
|
12
|
-
"agents": "
|
|
10
|
+
"manifest": "6ae21b90d390d4ccb2c1767ac554b97b16e35e54f132de4a5b8806e9de065a4b",
|
|
11
|
+
"packageJson": "9dc84723547541f1c99b7358247e99b192baa0b5ed9deec32a4842d2f0472667",
|
|
12
|
+
"agents": "9563c73635bb76c6ded59f5ef2dc0d34bf870634b5de6755f50093e95350464d"
|
|
13
13
|
},
|
|
14
14
|
"exports": [
|
|
15
15
|
".",
|
|
@@ -1903,7 +1903,7 @@
|
|
|
1903
1903
|
"polymorphicAssociations": 0,
|
|
1904
1904
|
"uuidColumns": 16
|
|
1905
1905
|
},
|
|
1906
|
-
"agentDoc": "# @happyvertical/smrt-secrets\n\nEnvelope encryption for per-tenant secret storage with key rotation and audit logging.\n\n## Encryption Architecture\n\n```\nSecret value → encrypted with TDEK (per-tenant Data Encryption Key)\n TDEK → wrapped with AMK (Application Master Key, from env SMRT_SECRET_MASTER_KEY)\n```\n\n## Models\n\n- **Secret**: `encryptedValue` (JSON envelope), `category`, `status` (active/disabled/expired), `expiresAt`, `accessCount`, `lastAccessedAt`. **No API/MCP exposure** (security). CLI: list-only.\n- **TenantKey**: per-tenant TDEK in wrapped form. Status: active/rotating/retired/compromised. **Not tenant-scoped itself** — it tracks keys FOR tenants.\n- **SecretAuditLog**: action (create/read/update/delete/rotate_key/disable/enable), result (success/failure/denied), user/IP tracking. CLI: list-only.\n\n## SecretService\n\n| Method | Behavior |\n|--------|----------|\n| `store(name, value, options)` | Encrypt + save. Upsert if exists. Uses `context=tenantId` for per-tenant uniqueness. |\n| `retrieve(name)` | Decrypt + audit + increment accessCount |\n| `diagnoseTenantSecretKeyDrift(tenantId)` | Report active secret/key drift without exposing values. Checks `secrets`, SDK `tenant_encryption_keys`, and SMRT `tenant_keys`. |\n| `repairTenantSecretKeyDrift(tenantId, opts)` | Explicit repair path for unrecoverable drift. Use `dryRun` first; destructive cleanup requires `confirmDeleteUnrecoverableData: true`. |\n| `rotateKey()` | Create new TDEK, mark old as retired |\n| `reencryptAll()` | Decrypt with old TDEK, re-encrypt with new — **must call separately after rotateKey()** |\n| `disable(name)` / `enable(name)` | Toggle status |\n\n## Gotchas\n\n- **Key rotation doesn't auto-re-encrypt**: call `reencryptAll()` separately after `rotateKey()`\n- **retrieve() increments accessCount**: every read is tracked\n- **TenantKey NOT tenant-scoped**: it stores keys for tenants but isn't filtered by tenant context\n- **Two key tables**: `tenant_encryption_keys` is the lower-level SDK table used by `SecretService` encryption; `tenant_keys` is the SMRT model table. Drift diagnosis reports both so an empty `tenant_keys` view is not confused with missing SDK key material.\n- **Repair is destructive only by confirmation**: `repairTenantSecretKeyDrift()` deletes unrecoverable encrypted rows only when `confirmDeleteUnrecoverableData: true` is explicit. Do not silently discard encrypted secrets.\n- **Expired secrets filtered by default**: pass `includeExpired: true` to list them\n- **TenantKeyCollection.cleanupRetiredKeys()**: hard-deletes after 90 days\n- **Audit logging optional but default**: failures logged to console, not thrown\n- **Audit rows outlive secrets**: `SecretAuditLog.secretId` uses the explicit\n same-package app-side-only FK option. It retains relationship metadata and an\n index, but emits no physical constraint because compliance logs are retained\n for 1-7 years while secrets may be deleted or purged during key-drift repair.\n\n## Known exceptions to monorepo standards\n\nPer `docs/content/standards.md §7`, tenant-aware models should normally apply\n`@TenantScoped({ mode: 'optional' })` from `@happyvertical/smrt-tenancy`. The three\nmodels in this package deviate intentionally; each `@smrt(...)` block carries an\ninline comment pointing back to this section.\n\n- **`Secret` (`src/models/Secret.ts`)** — uses the inline `tenantScoped: true` form\n on `@smrt()` instead of the `@TenantScoped` decorator. `SecretService.store()`\n performs manual scoping by populating `context = tenantId` on each row, so the\n `(slug, context)` upsert key from the base `SmrtObject` is what isolates secret\n names per tenant. Switching to the decorator without rethinking the upsert key\n would surface false-positive name collisions across tenants.\n- **`TenantKey` (`src/models/TenantKey.ts`)** — deliberately NOT tenant-scoped at\n all. The row carries a `tenantId` column because each TDEK belongs to a tenant,\n but key-rotation tooling, AMK rewrap jobs, and super-admin audits must query\n across tenants; the tenancy interceptor would silently filter rows those flows\n rely on.\n- **`SecretAuditLog` (`src/models/SecretAuditLog.ts`)** — uses the inline\n `tenantScoped: true` form rather than the decorator. Audit reads run in mixed\n contexts (tenant-scoped reports vs. super-admin compliance review). Cross-\n tenant audit queries should be wrapped in `withSuperAdminBypass()` from\n `@happyvertical/smrt-tenancy` at the call site — there are no such cross-\n tenant call sites in this package today, but consumers building compliance\n tooling should adopt that pattern explicitly rather than relying on\n decorator-implicit filtering. Its `secretId` relationship is also deliberately\n app-side-only so immutable audit history can survive deletion of the secret.\n",
|
|
1906
|
+
"agentDoc": "# @happyvertical/smrt-secrets\n\nEnvelope encryption for per-tenant secret storage with key rotation and audit logging.\n\n## Encryption Architecture\n\n```\nSecret value → encrypted with TDEK (per-tenant Data Encryption Key)\n TDEK → wrapped with AMK (Application Master Key, from env SMRT_SECRET_MASTER_KEY)\n```\n\n## Models\n\n- **Secret**: `encryptedValue` (JSON envelope), `category`, `status` (active/disabled/expired), `expiresAt`, `accessCount`, `lastAccessedAt`. **No API/MCP exposure** (security). CLI: list-only.\n- **TenantKey**: per-tenant TDEK in wrapped form. Status: active/rotating/retired/compromised. **Not tenant-scoped itself** — it tracks keys FOR tenants.\n- **SecretAuditLog**: action (create/read/update/delete/rotate_key/disable/enable), result (success/failure/denied), user/IP tracking. CLI: list-only.\n\n## SecretService\n\n| Method | Behavior |\n|--------|----------|\n| `store(name, value, options)` | Encrypt + save. Upsert if exists. Uses `context=tenantId` for per-tenant uniqueness. |\n| `retrieve(name)` | Decrypt + audit + increment accessCount |\n| `diagnoseTenantSecretKeyDrift(tenantId)` | Report active secret/key drift without exposing values. Checks `secrets`, SDK `tenant_encryption_keys`, and SMRT `tenant_keys`. |\n| `repairTenantSecretKeyDrift(tenantId, opts)` | Explicit repair path for unrecoverable drift. Use `dryRun` first; destructive cleanup requires `confirmDeleteUnrecoverableData: true`. |\n| `rotateKey()` | Create new TDEK, mark old as retired |\n| `reencryptAll()` | Decrypt with old TDEK, re-encrypt with new — **must call separately after rotateKey()** |\n| `disable(name)` / `enable(name)` | Toggle status |\n\n## Gotchas\n\n- **Key rotation doesn't auto-re-encrypt**: call `reencryptAll()` separately after `rotateKey()`\n- **retrieve() increments accessCount**: every read is tracked\n- **TenantKey NOT tenant-scoped**: it stores keys for tenants but isn't filtered by tenant context\n- **Two key tables**: `tenant_encryption_keys` is the lower-level SDK table used by `SecretService` encryption; `tenant_keys` is the SMRT model table. Drift diagnosis reports both so an empty `tenant_keys` view is not confused with missing SDK key material.\n- **Repair is destructive only by confirmation**: `repairTenantSecretKeyDrift()` deletes unrecoverable encrypted rows only when `confirmDeleteUnrecoverableData: true` is explicit. Do not silently discard encrypted secrets.\n- **Expired secrets filtered by default**: pass `includeExpired: true` to list them\n- **TenantKeyCollection.cleanupRetiredKeys()**: hard-deletes after 90 days\n- **Audit logging optional but default**: failures logged to console, not thrown\n- **Audit rows outlive secrets**: `SecretAuditLog.secretId` uses the explicit\n same-package app-side-only FK option. It retains relationship metadata and an\n index, but emits no physical constraint because compliance logs are retained\n for 1-7 years while secrets may be deleted or purged during key-drift repair.\n\n## Known exceptions to monorepo standards\n\nPer `docs/content/standards.md §7`, tenant-aware models should normally apply\n`@TenantScoped({ mode: 'optional' })` from `@happyvertical/smrt-tenancy`. The three\nmodels in this package deviate intentionally; each `@smrt(...)` block carries an\ninline comment pointing back to this section.\n\n- **`Secret` (`src/models/Secret.ts`)** — uses the inline `tenantScoped: true` form\n on `@smrt()` instead of the `@TenantScoped` decorator. `SecretService.store()`\n performs manual scoping by populating `context = tenantId` on each row, so the\n `(slug, context)` upsert key from the base `SmrtObject` is what isolates secret\n names per tenant. Switching to the decorator without rethinking the upsert key\n would surface false-positive name collisions across tenants.\n- **`TenantKey` (`src/models/TenantKey.ts`)** — deliberately NOT tenant-scoped at\n all. The row carries a `tenantId` column because each TDEK belongs to a tenant,\n but key-rotation tooling, AMK rewrap jobs, and super-admin audits must query\n across tenants; the tenancy interceptor would silently filter rows those flows\n rely on.\n- **`SecretAuditLog` (`src/models/SecretAuditLog.ts`)** — uses the inline\n `tenantScoped: true` form rather than the decorator. Audit reads run in mixed\n contexts (tenant-scoped reports vs. super-admin compliance review). Cross-\n tenant audit queries should be wrapped in `withSuperAdminBypass()` from\n `@happyvertical/smrt-tenancy` at the call site; the bypass applies only to\n classes declaring `allowSuperAdminBypass: true` (smrt#2973), which this\n model does not, so it stays tenant-filtered under bypass; cross-tenant\n compliance reads use `withSystemContext()` (the collection helpers' `null`\n tenant) unless the model is deliberately opted in — there are no such cross-\n tenant call sites in this package today, but consumers building compliance\n tooling should adopt that pattern explicitly rather than relying on\n decorator-implicit filtering. Its `secretId` relationship is also deliberately\n app-side-only so immutable audit history can survive deletion of the secret.\n",
|
|
1907
1907
|
"browser": {
|
|
1908
1908
|
"status": "server-only",
|
|
1909
1909
|
"issues": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-secrets",
|
|
3
|
-
"version": "0.55.
|
|
3
|
+
"version": "0.55.13",
|
|
4
4
|
"description": "Per-tenant secret management with envelope encryption for SMRT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@happyvertical/logger": "^0.103.
|
|
31
|
-
"@happyvertical/secrets": "^0.103.
|
|
32
|
-
"@happyvertical/smrt-core": "0.55.
|
|
33
|
-
"@happyvertical/smrt-tenancy": "0.55.
|
|
34
|
-
"@happyvertical/sql": "^0.103.
|
|
35
|
-
"@happyvertical/utils": "^0.103.
|
|
30
|
+
"@happyvertical/logger": "^0.103.2",
|
|
31
|
+
"@happyvertical/secrets": "^0.103.2",
|
|
32
|
+
"@happyvertical/smrt-core": "0.55.13",
|
|
33
|
+
"@happyvertical/smrt-tenancy": "0.55.13",
|
|
34
|
+
"@happyvertical/sql": "^0.103.2",
|
|
35
|
+
"@happyvertical/utils": "^0.103.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@happyvertical/smrt-vitest": "0.55.
|
|
38
|
+
"@happyvertical/smrt-vitest": "0.55.13",
|
|
39
39
|
"@types/node": "24.13.6",
|
|
40
40
|
"typescript": "6.0.3",
|
|
41
41
|
"vite": "8.1.4",
|