@tier0/sdk-v2 0.9.6 → 0.9.9

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.
Files changed (69) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +17 -5
  3. package/dist/cjs/capabilities.js +7 -4
  4. package/dist/cjs/capabilities.js.map +1 -1
  5. package/dist/cjs/client.d.ts +4 -6
  6. package/dist/cjs/data/bootstrap.js +6 -1
  7. package/dist/cjs/data/bootstrap.js.map +1 -1
  8. package/dist/cjs/data/define.d.ts +7 -0
  9. package/dist/cjs/data/define.js +21 -1
  10. package/dist/cjs/data/define.js.map +1 -1
  11. package/dist/cjs/data/schema.d.ts +1 -0
  12. package/dist/cjs/data/schema.js +9 -0
  13. package/dist/cjs/data/schema.js.map +1 -1
  14. package/dist/cjs/openapi/api.generated.d.ts +1 -0
  15. package/dist/cjs/openapi/codecs.generated.d.ts +54 -28
  16. package/dist/cjs/openapi/codecs.generated.js +1 -1
  17. package/dist/cjs/openapi/codecs.generated.js.map +1 -1
  18. package/dist/cjs/openapi/types.generated.d.ts +19 -2
  19. package/dist/cjs/openapi/types.generated.js.map +1 -1
  20. package/dist/cjs/source.d.ts +0 -3
  21. package/dist/cjs/source.js +0 -1
  22. package/dist/cjs/source.js.map +1 -1
  23. package/dist/cjs/uns-v2/generated.d.ts +73 -86
  24. package/dist/cjs/uns-v2/generated.js +20 -21
  25. package/dist/cjs/uns-v2/generated.js.map +1 -1
  26. package/dist/esm/capabilities.js +7 -4
  27. package/dist/esm/capabilities.js.map +1 -1
  28. package/dist/esm/client.d.ts +4 -6
  29. package/dist/esm/data/bootstrap.js +6 -1
  30. package/dist/esm/data/bootstrap.js.map +1 -1
  31. package/dist/esm/data/define.d.ts +7 -0
  32. package/dist/esm/data/define.js +19 -0
  33. package/dist/esm/data/define.js.map +1 -1
  34. package/dist/esm/data/schema.d.ts +1 -0
  35. package/dist/esm/data/schema.js +10 -1
  36. package/dist/esm/data/schema.js.map +1 -1
  37. package/dist/esm/openapi/api.generated.d.ts +1 -0
  38. package/dist/esm/openapi/codecs.generated.d.ts +54 -28
  39. package/dist/esm/openapi/codecs.generated.js +1 -1
  40. package/dist/esm/openapi/codecs.generated.js.map +1 -1
  41. package/dist/esm/openapi/types.generated.d.ts +19 -2
  42. package/dist/esm/openapi/types.generated.js.map +1 -1
  43. package/dist/esm/source.d.ts +0 -3
  44. package/dist/esm/source.js +0 -1
  45. package/dist/esm/source.js.map +1 -1
  46. package/dist/esm/uns-v2/generated.d.ts +73 -86
  47. package/dist/esm/uns-v2/generated.js +20 -21
  48. package/dist/esm/uns-v2/generated.js.map +1 -1
  49. package/package.json +2 -1
  50. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/SKILL.md +4 -1
  51. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/consistency.md +3 -3
  52. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/errors.md +4 -0
  53. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/modeling.md +32 -1
  54. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/read-write.md +3 -3
  55. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/schema-evolution.md +3 -2
  56. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md +5 -6
  57. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/changes.md +2 -2
  58. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/create.md +6 -6
  59. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/delete.md +1 -1
  60. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/read.md +1 -1
  61. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/update.md +8 -8
  62. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md +1 -1
  63. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/create.md +1 -1
  64. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/delete.md +1 -1
  65. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md +5 -2
  66. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/delete.md +27 -1
  67. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/namespace.md +17 -1
  68. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/read.md +22 -0
  69. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/state.md +0 -36
@@ -47,25 +47,28 @@ function diagnostics(value, fail) {
47
47
  return fail();
48
48
  return result;
49
49
  }
50
- const sourceOperations = ['read', 'configure', 'test', 'discover', 'enable', 'disable'];
50
+ const sourceOperations = ['read', 'configure', 'test', 'discover'];
51
+ const enterpriseSourceOperations = [...sourceOperations, 'enable', 'disable'];
51
52
  const streamOperations = ['read', 'configure', 'validate', 'deploy', 'execute', 'disable'];
52
53
  const resourceOperations = {
53
54
  source: ['test', 'discover', 'enable'],
54
55
  stream: ['deploy', 'execute'],
55
56
  'stream.requests.invoke.v1': ['invoke'],
56
57
  };
57
- function operationFields(value, code, fail) {
58
+ function operationFields(value, code, product, fail) {
58
59
  if (value.operations === undefined)
59
60
  return {};
60
61
  if (!Array.isArray(value.operations))
61
62
  return fail();
62
63
  const operations = [];
63
- const supported = code === 'source' ? sourceOperations : code === 'stream' ? streamOperations :
64
+ const supported = code === 'source' ? (product === 'cloud' ? sourceOperations : enterpriseSourceOperations) : code === 'stream' ? streamOperations :
64
65
  code === 'stream.requests.invoke.v1' ? ['invoke'] : [];
65
66
  const seen = new Set();
66
67
  for (const item of value.operations) {
67
68
  if (!record(item) || !text(item.operation))
68
69
  return fail();
70
+ if (product === 'cloud' && code === 'source' && ['enable', 'disable'].includes(item.operation))
71
+ return fail();
69
72
  if (!supported.includes(item.operation))
70
73
  continue;
71
74
  if (seen.has(item.operation))
@@ -120,7 +123,7 @@ function discovery(value, status, accepted) {
120
123
  code, state: item.state, reasonCode: item.reasonCode,
121
124
  contractVersions: [...item.contractVersions],
122
125
  ...diagnostics(item, fail),
123
- ...operationFields(item, code, fail),
126
+ ...operationFields(item, code, value.product, fail),
124
127
  });
125
128
  }
126
129
  const deprecations = [];
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["import { CloudTransport, CloudTransportError, type CloudTransportConfig } from './cloud-transport.js';\nimport { getClient, type HttpClient } from './openapi/client.js';\n\nexport type CapabilityCode = 'namespace.v2' | 'source' | 'stream' | 'stream.requests.v1' | 'stream.requests.invoke.v1';\nexport type CapabilityState = 'disabled' | 'not_supported' | 'unavailable' | 'readiness_unknown' | 'ready';\n\nexport interface CapabilityDiagnostics {\n reasonCode?: string;\n checkedAt?: string;\n validUntil?: string;\n retryAfterMs?: number;\n}\n\nexport interface CapabilityOperation extends CapabilityDiagnostics {\n operation: string;\n state: CapabilityState;\n reasonCode: string;\n requiresResourceCheck: boolean;\n}\n\nexport interface PublicCapability extends CapabilityDiagnostics {\n code: CapabilityCode;\n /** Discovery does not grant access to a resource or confirm a successful run. */\n state: CapabilityState;\n reasonCode: string;\n contractVersions: string[];\n operations?: CapabilityOperation[];\n}\n\nexport interface CapabilityDeprecation {\n contract: string;\n replacement?: string;\n sunsetAt?: string;\n}\n\nexport interface CapabilityDiscoverResponse {\n product: 'cloud' | 'enterprise';\n /** Trusted server configuration only; absent when unconfigured. */\n productVersion?: string;\n contractVersion: '2.0';\n apiContractVersions: string[];\n /** Public SDK contract labels, not npm package versions. */\n sdkContractVersions: string[];\n capabilities: PublicCapability[];\n deprecations: CapabilityDeprecation[];\n}\n\nexport interface CapabilityErrorInfo {\n status?: number;\n /** Gateway string code (including unknown future codes), or an SDK-local CAPABILITY_* code. */\n errorCode: string;\n}\n\nexport class CapabilityError extends Error {\n readonly status?: number;\n readonly errorCode: string;\n readonly retryable = false;\n\n constructor(message: string, info: CapabilityErrorInfo) {\n super(message);\n this.name = 'CapabilityError';\n this.status = info.status;\n this.errorCode = info.errorCode;\n }\n}\n\nconst contracts: Partial<Record<CapabilityCode, string[]>> = {\n 'namespace.v2': ['openapi/v2'],\n 'source': ['openapi/v2'],\n 'stream': ['openapi/v2'],\n};\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\nfunction text(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\nfunction strings(value: unknown): value is string[] {\n return Array.isArray(value) && value.every(text) && new Set(value).size === value.length;\n}\n\n\nfunction diagnostics(value: Record<string, unknown>, fail: () => never): CapabilityDiagnostics {\n const result: CapabilityDiagnostics = {};\n for (const field of ['reasonCode', 'checkedAt', 'validUntil'] as const) {\n if (value[field] === undefined) continue;\n if (!text(value[field])) return fail();\n if (field !== 'reasonCode' && (!/^\\d{4}-\\d\\d-\\d\\d[Tt]\\d\\d:\\d\\d:\\d\\d(?:\\.\\d+)?(?:[Zz]|[+-]\\d\\d:\\d\\d)$/.test(value[field]) ||\n !Number.isFinite(Date.parse(value[field])))) return fail();\n result[field] = value[field];\n }\n if (value.retryAfterMs !== undefined) {\n if (typeof value.retryAfterMs !== 'number' || !Number.isSafeInteger(value.retryAfterMs) || value.retryAfterMs < 0) return fail();\n result.retryAfterMs = value.retryAfterMs;\n }\n if (result.validUntil !== undefined && (value.state !== 'ready' || result.checkedAt === undefined ||\n Date.parse(result.validUntil) <= Date.parse(result.checkedAt))) return fail();\n return result;\n}\n\nconst sourceOperations = ['read', 'configure', 'test', 'discover', 'enable', 'disable'];\nconst streamOperations = ['read', 'configure', 'validate', 'deploy', 'execute', 'disable'];\nconst resourceOperations: Partial<Record<CapabilityCode, readonly string[]>> = {\n source: ['test', 'discover', 'enable'],\n stream: ['deploy', 'execute'],\n 'stream.requests.invoke.v1': ['invoke'],\n};\n\nfunction operationFields(value: Record<string, unknown>, code: CapabilityCode, fail: () => never): { operations?: CapabilityOperation[] } {\n if (value.operations === undefined) return {};\n if (!Array.isArray(value.operations)) return fail();\n const operations: CapabilityOperation[] = [];\n const supported = code === 'source' ? sourceOperations : code === 'stream' ? streamOperations :\n code === 'stream.requests.invoke.v1' ? ['invoke'] : [];\n const seen = new Set<string>();\n for (const item of value.operations) {\n if (!record(item) || !text(item.operation)) return fail();\n if (!supported.includes(item.operation)) continue;\n if (seen.has(item.operation)) return fail();\n seen.add(item.operation);\n if (!text(item.reasonCode) || typeof item.requiresResourceCheck !== 'boolean' ||\n (value.state === 'disabled' && item.state !== 'disabled') ||\n (resourceOperations[code]?.includes(item.operation) && !item.requiresResourceCheck) ||\n !['disabled', 'not_supported', 'unavailable', 'readiness_unknown', 'ready'].includes(item.state as string)) return fail();\n operations.push({operation: item.operation, state: item.state as CapabilityState, reasonCode: item.reasonCode,\n requiresResourceCheck: item.requiresResourceCheck, ...diagnostics(item, fail)});\n }\n return { operations };\n}\n\n/** Validate and explicitly project the frozen contract; unknown capabilities/extension fields are ignored. */\nfunction discovery(value: unknown, status: number, accepted: Partial<Record<CapabilityCode, string[]>>): CapabilityDiscoverResponse {\n const fail = (version = false): never => {\n throw new CapabilityError(version ? 'Unsupported capability contract version.' : 'Invalid capability discovery response.', {\n status, errorCode: version ? 'CAPABILITY_UNSUPPORTED_VERSION' : 'CAPABILITY_PROTOCOL_ERROR',\n });\n };\n if (!record(value)) return fail();\n if (!text(value.product) || !text(value.contractVersion) ||\n !strings(value.apiContractVersions) || !strings(value.sdkContractVersions) ||\n !Array.isArray(value.capabilities) || !Array.isArray(value.deprecations) ||\n (value.productVersion !== undefined && !text(value.productVersion))) return fail();\n if (!['cloud', 'enterprise'].includes(value.product) || value.contractVersion !== '2.0' ||\n !value.apiContractVersions.includes('openapi/v2')) return fail(true);\n\n const capabilities: PublicCapability[] = [];\n const seen = new Set<string>();\n for (const item of value.capabilities) {\n if (!record(item) || !text(item.code)) return fail();\n if (!Object.prototype.hasOwnProperty.call(accepted, item.code)) continue;\n const code = item.code as CapabilityCode;\n if (seen.has(code)) return fail();\n seen.add(code);\n if (!text(item.reasonCode) ||\n !['disabled', 'not_supported', 'unavailable', 'readiness_unknown', 'ready'].includes(item.state as string) ||\n !strings(item.contractVersions)) return fail();\n if (accepted[code]!.some(version =>\n !(item.contractVersions as string[]).includes(version) ||\n (version.startsWith('openapi/') && !(value.apiContractVersions as string[]).includes(version)))) return fail(true);\n capabilities.push({\n code, state: item.state as CapabilityState, reasonCode: item.reasonCode,\n contractVersions: [...item.contractVersions],\n ...diagnostics(item, fail),\n ...operationFields(item, code, fail),\n });\n }\n const deprecations: CapabilityDeprecation[] = [];\n for (const item of value.deprecations) {\n if (!record(item) || !text(item.contract) ||\n (item.replacement !== undefined && !text(item.replacement)) ||\n (item.sunsetAt !== undefined && !text(item.sunsetAt))) return fail();\n deprecations.push({ contract: item.contract,\n ...(item.replacement === undefined ? {} : { replacement: item.replacement as string }),\n ...(item.sunsetAt === undefined ? {} : { sunsetAt: item.sunsetAt as string }),\n });\n }\n return {\n product: value.product as CapabilityDiscoverResponse['product'], ...(value.productVersion === undefined ? {} : { productVersion: value.productVersion as string }),\n contractVersion: '2.0', apiContractVersions: [...value.apiContractVersions],\n sdkContractVersions: [...value.sdkContractVersions],\n capabilities, deprecations,\n };\n}\n\nexport class CapabilitiesClient {\n protected transport: CloudTransport;\n protected readonly contracts: Partial<Record<CapabilityCode, string[]>> = contracts;\n\n constructor(resolveClient: () => HttpClient = getClient, config: CloudTransportConfig = {}) {\n this.transport = new CloudTransport(resolveClient, config);\n }\n\n /** Workspace comes exclusively from the authenticated key. One POST, no automatic retries or caching. */\n async discover(): Promise<CapabilityDiscoverResponse> {\n if (arguments.length !== 0) throw new TypeError('Tier0 SDK: capability discovery accepts no arguments.');\n let response: Awaited<ReturnType<CloudTransport['post']>>;\n try {\n response = await this.transport.post('/openapi/v2/capabilities/discover', {});\n } catch (error) {\n if (!(error instanceof CloudTransportError)) throw error;\n throw new CapabilityError('Capability discovery HTTP exchange failed.', {\n status: error.status, errorCode: `CAPABILITY_${error.kind}`,\n });\n }\n const { value, status, ok } = response;\n if (!ok) {\n if (!record(value) || !text(value.errorCode) || typeof value.message !== 'string') {\n throw new CapabilityError('Invalid capability error response.', { status, errorCode: 'CAPABILITY_PROTOCOL_ERROR' });\n }\n throw new CapabilityError(value.message, { status, errorCode: value.errorCode });\n }\n return discovery(value, status, this.contracts);\n }\n}\n\n/** Uses configureClient()/runtime environment, resolving the host and workspace key on every call. */\nexport const capabilities = new CapabilitiesClient();\n"]}
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["import { CloudTransport, CloudTransportError, type CloudTransportConfig } from './cloud-transport.js';\nimport { getClient, type HttpClient } from './openapi/client.js';\n\nexport type CapabilityCode = 'namespace.v2' | 'source' | 'stream' | 'stream.requests.v1' | 'stream.requests.invoke.v1';\nexport type CapabilityState = 'disabled' | 'not_supported' | 'unavailable' | 'readiness_unknown' | 'ready';\n\nexport interface CapabilityDiagnostics {\n reasonCode?: string;\n checkedAt?: string;\n validUntil?: string;\n retryAfterMs?: number;\n}\n\nexport interface CapabilityOperation extends CapabilityDiagnostics {\n operation: string;\n state: CapabilityState;\n reasonCode: string;\n requiresResourceCheck: boolean;\n}\n\nexport interface PublicCapability extends CapabilityDiagnostics {\n code: CapabilityCode;\n /** Discovery does not grant access to a resource or confirm a successful run. */\n state: CapabilityState;\n reasonCode: string;\n contractVersions: string[];\n operations?: CapabilityOperation[];\n}\n\nexport interface CapabilityDeprecation {\n contract: string;\n replacement?: string;\n sunsetAt?: string;\n}\n\nexport interface CapabilityDiscoverResponse {\n product: 'cloud' | 'enterprise';\n /** Trusted server configuration only; absent when unconfigured. */\n productVersion?: string;\n contractVersion: '2.0';\n apiContractVersions: string[];\n /** Public SDK contract labels, not npm package versions. */\n sdkContractVersions: string[];\n capabilities: PublicCapability[];\n deprecations: CapabilityDeprecation[];\n}\n\nexport interface CapabilityErrorInfo {\n status?: number;\n /** Gateway string code (including unknown future codes), or an SDK-local CAPABILITY_* code. */\n errorCode: string;\n}\n\nexport class CapabilityError extends Error {\n readonly status?: number;\n readonly errorCode: string;\n readonly retryable = false;\n\n constructor(message: string, info: CapabilityErrorInfo) {\n super(message);\n this.name = 'CapabilityError';\n this.status = info.status;\n this.errorCode = info.errorCode;\n }\n}\n\nconst contracts: Partial<Record<CapabilityCode, string[]>> = {\n 'namespace.v2': ['openapi/v2'],\n 'source': ['openapi/v2'],\n 'stream': ['openapi/v2'],\n};\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\nfunction text(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\nfunction strings(value: unknown): value is string[] {\n return Array.isArray(value) && value.every(text) && new Set(value).size === value.length;\n}\n\n\nfunction diagnostics(value: Record<string, unknown>, fail: () => never): CapabilityDiagnostics {\n const result: CapabilityDiagnostics = {};\n for (const field of ['reasonCode', 'checkedAt', 'validUntil'] as const) {\n if (value[field] === undefined) continue;\n if (!text(value[field])) return fail();\n if (field !== 'reasonCode' && (!/^\\d{4}-\\d\\d-\\d\\d[Tt]\\d\\d:\\d\\d:\\d\\d(?:\\.\\d+)?(?:[Zz]|[+-]\\d\\d:\\d\\d)$/.test(value[field]) ||\n !Number.isFinite(Date.parse(value[field])))) return fail();\n result[field] = value[field];\n }\n if (value.retryAfterMs !== undefined) {\n if (typeof value.retryAfterMs !== 'number' || !Number.isSafeInteger(value.retryAfterMs) || value.retryAfterMs < 0) return fail();\n result.retryAfterMs = value.retryAfterMs;\n }\n if (result.validUntil !== undefined && (value.state !== 'ready' || result.checkedAt === undefined ||\n Date.parse(result.validUntil) <= Date.parse(result.checkedAt))) return fail();\n return result;\n}\n\nconst sourceOperations = ['read', 'configure', 'test', 'discover'];\nconst enterpriseSourceOperations = [...sourceOperations, 'enable', 'disable'];\nconst streamOperations = ['read', 'configure', 'validate', 'deploy', 'execute', 'disable'];\nconst resourceOperations: Partial<Record<CapabilityCode, readonly string[]>> = {\n source: ['test', 'discover', 'enable'],\n stream: ['deploy', 'execute'],\n 'stream.requests.invoke.v1': ['invoke'],\n};\n\nfunction operationFields(value: Record<string, unknown>, code: CapabilityCode, product: string, fail: () => never): { operations?: CapabilityOperation[] } {\n if (value.operations === undefined) return {};\n if (!Array.isArray(value.operations)) return fail();\n const operations: CapabilityOperation[] = [];\n const supported = code === 'source' ? (product === 'cloud' ? sourceOperations : enterpriseSourceOperations) : code === 'stream' ? streamOperations :\n code === 'stream.requests.invoke.v1' ? ['invoke'] : [];\n const seen = new Set<string>();\n for (const item of value.operations) {\n if (!record(item) || !text(item.operation)) return fail();\n if (product === 'cloud' && code === 'source' && ['enable', 'disable'].includes(item.operation)) return fail();\n if (!supported.includes(item.operation)) continue;\n if (seen.has(item.operation)) return fail();\n seen.add(item.operation);\n if (!text(item.reasonCode) || typeof item.requiresResourceCheck !== 'boolean' ||\n (value.state === 'disabled' && item.state !== 'disabled') ||\n (resourceOperations[code]?.includes(item.operation) && !item.requiresResourceCheck) ||\n !['disabled', 'not_supported', 'unavailable', 'readiness_unknown', 'ready'].includes(item.state as string)) return fail();\n operations.push({operation: item.operation, state: item.state as CapabilityState, reasonCode: item.reasonCode,\n requiresResourceCheck: item.requiresResourceCheck, ...diagnostics(item, fail)});\n }\n return { operations };\n}\n\n/** Validate and explicitly project the frozen contract; unknown capabilities/extension fields are ignored. */\nfunction discovery(value: unknown, status: number, accepted: Partial<Record<CapabilityCode, string[]>>): CapabilityDiscoverResponse {\n const fail = (version = false): never => {\n throw new CapabilityError(version ? 'Unsupported capability contract version.' : 'Invalid capability discovery response.', {\n status, errorCode: version ? 'CAPABILITY_UNSUPPORTED_VERSION' : 'CAPABILITY_PROTOCOL_ERROR',\n });\n };\n if (!record(value)) return fail();\n if (!text(value.product) || !text(value.contractVersion) ||\n !strings(value.apiContractVersions) || !strings(value.sdkContractVersions) ||\n !Array.isArray(value.capabilities) || !Array.isArray(value.deprecations) ||\n (value.productVersion !== undefined && !text(value.productVersion))) return fail();\n if (!['cloud', 'enterprise'].includes(value.product) || value.contractVersion !== '2.0' ||\n !value.apiContractVersions.includes('openapi/v2')) return fail(true);\n\n const capabilities: PublicCapability[] = [];\n const seen = new Set<string>();\n for (const item of value.capabilities) {\n if (!record(item) || !text(item.code)) return fail();\n if (!Object.prototype.hasOwnProperty.call(accepted, item.code)) continue;\n const code = item.code as CapabilityCode;\n if (seen.has(code)) return fail();\n seen.add(code);\n if (!text(item.reasonCode) ||\n !['disabled', 'not_supported', 'unavailable', 'readiness_unknown', 'ready'].includes(item.state as string) ||\n !strings(item.contractVersions)) return fail();\n if (accepted[code]!.some(version =>\n !(item.contractVersions as string[]).includes(version) ||\n (version.startsWith('openapi/') && !(value.apiContractVersions as string[]).includes(version)))) return fail(true);\n capabilities.push({\n code, state: item.state as CapabilityState, reasonCode: item.reasonCode,\n contractVersions: [...item.contractVersions],\n ...diagnostics(item, fail),\n ...operationFields(item, code, value.product, fail),\n });\n }\n const deprecations: CapabilityDeprecation[] = [];\n for (const item of value.deprecations) {\n if (!record(item) || !text(item.contract) ||\n (item.replacement !== undefined && !text(item.replacement)) ||\n (item.sunsetAt !== undefined && !text(item.sunsetAt))) return fail();\n deprecations.push({ contract: item.contract,\n ...(item.replacement === undefined ? {} : { replacement: item.replacement as string }),\n ...(item.sunsetAt === undefined ? {} : { sunsetAt: item.sunsetAt as string }),\n });\n }\n return {\n product: value.product as CapabilityDiscoverResponse['product'], ...(value.productVersion === undefined ? {} : { productVersion: value.productVersion as string }),\n contractVersion: '2.0', apiContractVersions: [...value.apiContractVersions],\n sdkContractVersions: [...value.sdkContractVersions],\n capabilities, deprecations,\n };\n}\n\nexport class CapabilitiesClient {\n protected transport: CloudTransport;\n protected readonly contracts: Partial<Record<CapabilityCode, string[]>> = contracts;\n\n constructor(resolveClient: () => HttpClient = getClient, config: CloudTransportConfig = {}) {\n this.transport = new CloudTransport(resolveClient, config);\n }\n\n /** Workspace comes exclusively from the authenticated key. One POST, no automatic retries or caching. */\n async discover(): Promise<CapabilityDiscoverResponse> {\n if (arguments.length !== 0) throw new TypeError('Tier0 SDK: capability discovery accepts no arguments.');\n let response: Awaited<ReturnType<CloudTransport['post']>>;\n try {\n response = await this.transport.post('/openapi/v2/capabilities/discover', {});\n } catch (error) {\n if (!(error instanceof CloudTransportError)) throw error;\n throw new CapabilityError('Capability discovery HTTP exchange failed.', {\n status: error.status, errorCode: `CAPABILITY_${error.kind}`,\n });\n }\n const { value, status, ok } = response;\n if (!ok) {\n if (!record(value) || !text(value.errorCode) || typeof value.message !== 'string') {\n throw new CapabilityError('Invalid capability error response.', { status, errorCode: 'CAPABILITY_PROTOCOL_ERROR' });\n }\n throw new CapabilityError(value.message, { status, errorCode: value.errorCode });\n }\n return discovery(value, status, this.contracts);\n }\n}\n\n/** Uses configureClient()/runtime environment, resolving the host and workspace key on every call. */\nexport const capabilities = new CapabilitiesClient();\n"]}
@@ -62,6 +62,7 @@ export declare function createClient(config?: Tier0ClientConfig): Readonly<{
62
62
  status: string;
63
63
  }>;
64
64
  get: (body: import("./index.js").components["schemas"]["SdknotificationsGetRequest"], options?: import("./openapi/client.js").RequestOptions) => Promise<{
65
+ channels: import("./index.js").components["schemas"]["NotificationChannelResult"][];
65
66
  completedAt?: string;
66
67
  createdAt: string;
67
68
  errorCode?: string;
@@ -218,9 +219,6 @@ export declare function createClient(config?: Tier0ClientConfig): Readonly<{
218
219
  protocols: Readonly<{
219
220
  list: (request: import("./index.js").UnsV2SourceProtocolsListReq, options?: import("./openapi/client.js").RequestOptions) => Promise<import("./index.js").UnsV2SourceProtocolsListResponse>;
220
221
  }>;
221
- state: Readonly<{
222
- update: (request: import("./index.js").UnsV2SourceStateUpdateReq, options?: import("./openapi/client.js").RequestOptions) => Promise<import("./index.js").UnsV2SourceStateUpdateResponse>;
223
- }>;
224
222
  runtime: Readonly<{
225
223
  get: (request: import("./index.js").UnsV2SourceRuntimeGetReq, options?: import("./openapi/client.js").RequestOptions) => Promise<import("./index.js").UnsV2SourceRuntimeGetResponse>;
226
224
  }>;
@@ -340,6 +338,7 @@ export declare function createClient(config?: Tier0ClientConfig): Readonly<{
340
338
  status: string;
341
339
  }>;
342
340
  get: (body: import("./index.js").components["schemas"]["SdknotificationsGetRequest"], options?: import("./openapi/client.js").RequestOptions) => Promise<{
341
+ channels: import("./index.js").components["schemas"]["NotificationChannelResult"][];
343
342
  completedAt?: string;
344
343
  createdAt: string;
345
344
  errorCode?: string;
@@ -574,6 +573,7 @@ export declare const client: Readonly<{
574
573
  status: string;
575
574
  }>;
576
575
  get: (body: import("./index.js").components["schemas"]["SdknotificationsGetRequest"], options?: import("./openapi/client.js").RequestOptions) => Promise<{
576
+ channels: import("./index.js").components["schemas"]["NotificationChannelResult"][];
577
577
  completedAt?: string;
578
578
  createdAt: string;
579
579
  errorCode?: string;
@@ -730,9 +730,6 @@ export declare const client: Readonly<{
730
730
  protocols: Readonly<{
731
731
  list: (request: import("./index.js").UnsV2SourceProtocolsListReq, options?: import("./openapi/client.js").RequestOptions) => Promise<import("./index.js").UnsV2SourceProtocolsListResponse>;
732
732
  }>;
733
- state: Readonly<{
734
- update: (request: import("./index.js").UnsV2SourceStateUpdateReq, options?: import("./openapi/client.js").RequestOptions) => Promise<import("./index.js").UnsV2SourceStateUpdateResponse>;
735
- }>;
736
733
  runtime: Readonly<{
737
734
  get: (request: import("./index.js").UnsV2SourceRuntimeGetReq, options?: import("./openapi/client.js").RequestOptions) => Promise<import("./index.js").UnsV2SourceRuntimeGetResponse>;
738
735
  }>;
@@ -852,6 +849,7 @@ export declare const client: Readonly<{
852
849
  status: string;
853
850
  }>;
854
851
  get: (body: import("./index.js").components["schemas"]["SdknotificationsGetRequest"], options?: import("./openapi/client.js").RequestOptions) => Promise<{
852
+ channels: import("./index.js").components["schemas"]["NotificationChannelResult"][];
855
853
  completedAt?: string;
856
854
  createdAt: string;
857
855
  errorCode?: string;
@@ -190,7 +190,12 @@ export function createBootstrap(config) {
190
190
  collectionIds.set(result.alias.toLowerCase(), result.collectionId);
191
191
  const notes = result.ignored ?? [];
192
192
  const annotations = notes.filter((note) => note.reason === 'ANNOTATION_NOT_APPLIED');
193
- const wider = notes.filter((note) => note.reason !== 'ANNOTATION_NOT_APPLIED');
193
+ const directories = notes.filter((note) => note.reason === 'DIRECTORY_PATH_NOT_APPLIED');
194
+ const wider = notes.filter((note) => note.reason !== 'ANNOTATION_NOT_APPLIED' && note.reason !== 'DIRECTORY_PATH_NOT_APPLIED');
195
+ if (directories.length > 0) {
196
+ logger.warn(`[data] ensure keeps existing collection locations; not applied: ${directories.map((note) => notePath(result.alias, note)).join(', ')}. ` +
197
+ 'A directoryPath declaration only places a new collection. Move existing collections explicitly through metadata operations when authorized.');
198
+ }
194
199
  if (wider.length > 0) {
195
200
  logger.info(`[data] "${result.alias}" storage is wider than this declaration (or has retired parts); ignored: ` +
196
201
  wider.map((note) => `${note.path || '(root)'} ${note.reason ?? ''}`.trim()).join(', '));
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../src/data/bootstrap.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First-access bootstrap: one batched `ensure` of every declared collection.\n *\n * - ensure only creates or widens; storage never narrows from here, so old\n * and new code may cold-start in any order.\n * - The result is memoized per client, i.e. per server process; a client\n * built from edited declarations ensures again.\n * Failures are not memoized: a later call retries (an imported App may\n * answer \"hosted App is not ready\").\n * - Seed documents are inserted only for collections ensure reports as\n * `created`: fixed `_id`s, atomic chunks of 200 with a stable idempotency\n * key per chunk, so a failed chunk (outcome unknown, or marked safe to\n * resend) is replayed after a short wait instead of duplicated. Seed writes\n * never carry a data subject.\n * - Preview throws on SCHEMA_CONFLICT and warnings so the worker sees them;\n * a deployment logs them and keeps serving with the IDs it has.\n * - Self-healing: a Preview reset hard-deletes collections, and a worker or\n * admin may archive one, while this process still holds the old IDs. A\n * record call that fails with `data.reason` COLLECTION_NOT_FOUND or\n * COLLECTION_NOT_GRANTED drops the memo, ensures again (seeding what is created)\n * and retries the call once, but only when a collection ID actually\n * changed. Rebuilds are limited to one per REBUILD_INTERVAL_MS per client;\n * APP_GRANT_REVOKED is never retried (ensure itself reports it).\n * - `ignored` notes never fail a request. ensure never writes annotations, so\n * an edited name, `.describe()` or collection description comes back as\n * ANNOTATION_NOT_APPLIED; it is logged as a warning pointing at\n * metadata:updateOne for names, or schema:replace for schema annotations.\n */\nimport { createHash } from 'node:crypto';\nimport type { DataCall } from './call.js';\nimport { assertNoWriteErrors, MAX_ATOMIC_ITEMS } from './collection.js';\nimport type { CollectionDefinition } from './define.js';\nimport { ACCESS_REASONS, DataError } from './error.js';\nimport { compileCollection, validateDocument, type CompiledCollection } from './schema.js';\n\nexport type DataEnvironment = 'preview' | 'deployed';\n\nexport interface EnsureWarning {\n code: string;\n path?: string;\n message?: string;\n}\n\nexport interface EnsureNote {\n path: string;\n reason?: string;\n message?: string;\n}\n\nexport interface EnsureResult {\n alias: string;\n collectionId: string;\n revision: number;\n status: 'created' | 'unchanged' | 'widened';\n ignored?: EnsureNote[];\n warnings?: EnsureWarning[];\n indexStatus?: unknown[];\n}\n\nexport interface EnsureConflict {\n alias: string;\n collectionId?: string;\n path?: string;\n reason?: string;\n current?: string;\n declared?: string;\n}\n\nexport interface EnsureState {\n appId?: string;\n results: EnsureResult[];\n /** Lower-cased alias → collection ID. */\n collectionIds: Map<string, string>;\n /** Declarations that conflicted in a deployment (served with their existing ID, if any). */\n conflicts: EnsureConflict[];\n}\n\nexport interface Logger {\n info(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n}\n\nexport interface BootstrapConfig {\n call: DataCall;\n collections: readonly CollectionDefinition[];\n environment: DataEnvironment;\n logger: Logger;\n}\n\nconst SEED_ATTEMPTS = 3;\n/** Wait before replaying seed chunk attempt n+1: n × this. */\nexport const SEED_RETRY_MS = 1_000;\n\n/** At most one self-healing rebuild per client in this window. */\nexport const REBUILD_INTERVAL_MS = 30_000;\n\n/**\n * Whether a record call failed because the collection ID it used is gone or\n * no longer granted, by UNS's stable `data.reason` code. Archive and Preview\n * purge also remove the App grant, so most stale IDs answer\n * COLLECTION_NOT_GRANTED or COLLECTION_NOT_FOUND. APP_PERMISSION_MISSING (the\n * key lacks e.g. `uns.delete`) and APP_GRANT_REVOKED are not stale IDs.\n */\nexport function isStaleCollectionError(error: unknown): boolean {\n return (\n error instanceof DataError &&\n (error.reason === ACCESS_REASONS.notGranted || error.reason === ACCESS_REASONS.notFound)\n );\n}\n\nfunction sameCollectionIds(a: EnsureState, b: EnsureState): boolean {\n if (a.collectionIds.size !== b.collectionIds.size) return false;\n for (const [alias, id] of a.collectionIds) {\n if (b.collectionIds.get(alias) !== id) return false;\n }\n return true;\n}\n\n/** Idempotency key of one seed chunk (UNS keys are at most 96 characters). */\nfunction seedChunkKey(collectionId: string, chunk: number): string {\n return `seed-${createHash('sha256').update(collectionId).digest('hex').slice(0, 40)}-${chunk}`;\n}\n\n/** What to do about each SCHEMA_CONFLICT reason (CloudAppCollectionConflict.reason). */\nconst CONFLICT_HINTS: Record<string, string> = {\n TYPE_CONFLICT: \"a field's type cannot change; use a new field name and backfill with updateMany\",\n LIMIT_EXCEEDED: 'the joined schema exceeds a UNS limit (depth, properties, enum values or indexes); split the structure',\n OPEN_OBJECT: 'every object must be closed; declare it with z.object',\n ALIAS_IN_USE: 'the alias belongs to another collection; pick another alias',\n NAME_IN_USE: 'the business name belongs to another collection in this folder; pick another name and keep the stable alias',\n INVALID_INDEX: 'fix the index declaration',\n JOIN_UNSUPPORTED:\n 'the stored schema holds a node the declaration cannot widen (e.g. enum values outside its range); repair it with schema:replace via the tier0 MCP',\n DATA_RULE_FIELD:\n 'an employee data rule (ownerField / stateField) uses this field; keep it required with the same type, or ask a workspace admin to change the rule',\n};\n\nfunction describeConflicts(conflicts: EnsureConflict[]): string {\n return conflicts\n .map((conflict) => {\n const where = `${conflict.alias}${conflict.path ? `.${conflict.path}` : ''}`;\n const types = conflict.current || conflict.declared ? ` (stored ${conflict.current ?? '?'}, declared ${conflict.declared ?? '?'})` : '';\n const hint = conflict.reason && CONFLICT_HINTS[conflict.reason] ? ` — ${CONFLICT_HINTS[conflict.reason]}` : '';\n return ` - ${where}: ${conflict.reason ?? 'conflict'}${types}${hint}`;\n })\n .join('\\n');\n}\n\nfunction notePath(alias: string, note: EnsureNote): string {\n return note.path ? `${alias}.${note.path}` : alias;\n}\n\nfunction describeWarnings(results: EnsureResult[]): string {\n return results\n .flatMap((result) =>\n (result.warnings ?? []).map(\n (warning) => ` - ${result.alias}${warning.path ? `.${warning.path}` : ''}: ${warning.code}${warning.message ? ` — ${warning.message}` : ''}`,\n ),\n )\n .join('\\n');\n}\n\nexport function createBootstrap(config: BootstrapConfig) {\n const { call, collections, environment, logger } = config;\n let pending: Promise<EnsureState> | null = null;\n let lastRebuild = Number.NEGATIVE_INFINITY;\n\n async function requestEnsure(items: CompiledCollection[]) {\n // ensure is App-level work: it never carries the employee data subject.\n return call<{ appId?: string; results: EnsureResult[] }>('appCollectionsEnsure', { collections: items });\n }\n\n async function insertSeedChunk(collectionId: string, chunk: number, documents: { id?: string; data: Record<string, unknown> }[]) {\n for (let attempt = 1; ; attempt += 1) {\n try {\n const result = await call<{ writeErrors?: Record<string, unknown>[] }>('recordBulkWrite', {\n collectionId,\n operations: documents.map(document => ({ insertOne: document })),\n ordered: true,\n atomic: true,\n idempotencyKey: seedChunkKey(collectionId, chunk),\n });\n assertNoWriteErrors(result, 'seed');\n return;\n } catch (error) {\n // The chunk key is stable, so replaying is safe even when the outcome is unknown: a chunk\n // that did commit replays its receipt. Wait first, so a write still running can finish.\n if (!(error instanceof DataError) || !(error.outcomeUnknown || error.retry.safe) || attempt >= SEED_ATTEMPTS) throw error;\n await new Promise((resolve) => setTimeout(resolve, SEED_RETRY_MS * attempt));\n }\n }\n }\n\n async function writeSeeds(results: EnsureResult[]) {\n for (const result of results) {\n if (result.status !== 'created') continue;\n const definition = collections.find((candidate) => candidate.alias.toLowerCase() === result.alias.toLowerCase());\n const seed = definition?.seed;\n if (!definition || !seed || seed.length === 0) continue;\n try {\n const documents = seed.map((document) => {\n const { id, data } = validateDocument(definition, document as Record<string, unknown>);\n return { id, data };\n });\n for (let start = 0; start < documents.length; start += MAX_ATOMIC_ITEMS) {\n await insertSeedChunk(result.collectionId, start / MAX_ATOMIC_ITEMS, documents.slice(start, start + MAX_ATOMIC_ITEMS));\n }\n logger.info(`[data] seeded ${documents.length} record(s) into \"${result.alias}\"`);\n } catch (error) {\n // The collection exists now; a later ensure reports \"unchanged\" and\n // never re-seeds, so the failure must be visible in the server log.\n logger.error(`[data] seed for new collection \"${result.alias}\" failed; it keeps the chunks written so far:`, error);\n }\n }\n }\n\n async function run(payload: CompiledCollection[]): Promise<EnsureState> {\n const conflicts: EnsureConflict[] = [];\n let remaining = payload;\n let response: { appId?: string; results: EnsureResult[] } = { results: [] };\n while (remaining.length > 0) {\n try {\n response = await requestEnsure(remaining);\n break;\n } catch (error) {\n if (!(error instanceof DataError) || error.code !== 'SCHEMA_CONFLICT') throw error;\n const reported = Array.isArray(error.details.conflicts) ? (error.details.conflicts as EnsureConflict[]) : [];\n const summary = describeConflicts(reported);\n if (environment === 'preview') {\n throw new DataError({\n message:\n `The collection declarations conflict with the stored collection schemas; nothing was changed:\\n${summary}`,\n status: 409,\n code: 'SCHEMA_CONFLICT',\n upstreamStatus: error.upstreamStatus,\n requestId: error.requestId,\n execution: error.execution,\n attempts: error.attempts,\n details: error.details,\n });\n }\n // A deployment keeps serving: drop the conflicting declarations (the\n // whole batch was rejected) and ensure the rest again.\n const conflicting = new Set(reported.map((conflict) => conflict.alias.toLowerCase()));\n const next = remaining.filter((item) => !conflicting.has(item.alias.toLowerCase()));\n if (next.length === remaining.length) throw error;\n logger.error(`[data] ensure: declarations conflict with stored schemas; serving them unchanged:\\n${summary}`);\n conflicts.push(...reported);\n remaining = next;\n }\n }\n\n const results = response.results ?? [];\n const collectionIds = new Map<string, string>();\n for (const conflict of conflicts) {\n if (conflict.collectionId) collectionIds.set(conflict.alias.toLowerCase(), conflict.collectionId);\n }\n for (const result of results) {\n collectionIds.set(result.alias.toLowerCase(), result.collectionId);\n const notes = result.ignored ?? [];\n const annotations = notes.filter((note) => note.reason === 'ANNOTATION_NOT_APPLIED');\n const wider = notes.filter((note) => note.reason !== 'ANNOTATION_NOT_APPLIED');\n if (wider.length > 0) {\n logger.info(\n `[data] \"${result.alias}\" storage is wider than this declaration (or has retired parts); ignored: ` +\n wider.map((note) => `${note.path || '(root)'} ${note.reason ?? ''}`.trim()).join(', '),\n );\n }\n if (annotations.length > 0) {\n // A hint, not an error: storage keeps its annotations and serves as before.\n logger.warn(\n `[data] ensure does not change stored names/titles/descriptions; not applied: ${annotations.map((note) => notePath(result.alias, note)).join(', ')}. ` +\n `Rename with metadata:updateOne via the tier0 MCP; apply schema annotations with schema:replace, selecting alias, recordSchema, indexes and description from compileCollection(...).`,\n );\n }\n }\n\n await writeSeeds(results);\n\n const warnings = describeWarnings(results);\n if (warnings) {\n if (environment === 'preview') {\n throw new DataError({\n message:\n `Collections were ensured with warnings:\\n${warnings}\\n` +\n 'REQUIRED_NOT_ENFORCED: make the field optional again or narrow explicitly with schema:replace via the tier0 MCP. ' +\n 'INDEX_BUILD_FAILED: fix the duplicate or invalid data, then the next ensure retries the index.',\n status: 500,\n code: 'SCHEMA_WARNINGS',\n // ensure did apply; only the warnings fail the Preview request.\n execution: 'committed',\n details: { results },\n });\n }\n logger.warn(`[data] ensure warnings:\\n${warnings}`);\n }\n\n return { appId: response.appId, results, collectionIds, conflicts };\n }\n\n /** Ensures every declaration once per client; a failure is forgotten so the next call retries. */\n function ensure(): Promise<EnsureState> {\n pending ??= Promise.resolve()\n .then(() => run(collections.map(compileCollection)))\n .catch((error) => {\n pending = null;\n throw error;\n });\n return pending;\n }\n\n /**\n * Re-ensures after `before` turned out stale. Joins a rebuild already in\n * flight; otherwise rebuilds at most once per REBUILD_INTERVAL_MS. Resolves\n * whether any collection ID changed; ensure errors (APP_GRANT_REVOKED, …)\n * propagate.\n */\n async function rebuild(before: EnsureState, cause: DataError): Promise<boolean> {\n // Only owned IDs can be recovered by ensure; shared references must keep their original error.\n const failedId = cause.details.collectionId;\n if (typeof failedId === 'string' && ![...before.collectionIds.values()].includes(failedId)) return false;\n const current = ensure();\n const latest = await current;\n if (latest !== before) return !sameCollectionIds(before, latest);\n if (pending !== current) return !sameCollectionIds(before, await ensure());\n const now = Date.now();\n if (now - lastRebuild < REBUILD_INTERVAL_MS) return false;\n lastRebuild = now;\n logger.warn(`[data] a collection ID is no longer usable (${cause.code}: ${cause.message}); ensuring collections again`);\n pending = null;\n return !sameCollectionIds(before, await ensure());\n }\n\n /**\n * Runs one data call; when it fails on a stale collection ID, rebuilds and\n * runs it once more if an ID changed. `retry: false` (calls continuing a\n * cursor or resumeAfter token of the old collection) only rebuilds.\n */\n async function recover<R>(fn: () => Promise<R>, options: { retry?: boolean } = {}): Promise<R> {\n const before = await ensure();\n try {\n return await fn();\n } catch (error) {\n if (!isStaleCollectionError(error)) throw error;\n const changed = await rebuild(before, error as DataError);\n if (!changed || options.retry === false) throw error;\n return fn();\n }\n }\n\n async function resolve(definition: CollectionDefinition): Promise<string> {\n const state = await ensure();\n const id = state.collectionIds.get(definition.alias.toLowerCase());\n if (!id) {\n throw new DataError({\n message: `Collection \"${definition.alias}\" is unavailable: ensure did not return it (see the server log).`,\n status: 503,\n code: 'COLLECTION_UNAVAILABLE',\n });\n }\n return id;\n }\n\n return { ensure, resolve, recover, rebuild };\n}\n"]}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../src/data/bootstrap.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First-access bootstrap: one batched `ensure` of every declared collection.\n *\n * - ensure only creates or widens; storage never narrows from here, so old\n * and new code may cold-start in any order.\n * - The result is memoized per client, i.e. per server process; a client\n * built from edited declarations ensures again.\n * Failures are not memoized: a later call retries (an imported App may\n * answer \"hosted App is not ready\").\n * - Seed documents are inserted only for collections ensure reports as\n * `created`: fixed `_id`s, atomic chunks of 200 with a stable idempotency\n * key per chunk, so a failed chunk (outcome unknown, or marked safe to\n * resend) is replayed after a short wait instead of duplicated. Seed writes\n * never carry a data subject.\n * - Preview throws on SCHEMA_CONFLICT and warnings so the worker sees them;\n * a deployment logs them and keeps serving with the IDs it has.\n * - Self-healing: a Preview reset hard-deletes collections, and a worker or\n * admin may archive one, while this process still holds the old IDs. A\n * record call that fails with `data.reason` COLLECTION_NOT_FOUND or\n * COLLECTION_NOT_GRANTED drops the memo, ensures again (seeding what is created)\n * and retries the call once, but only when a collection ID actually\n * changed. Rebuilds are limited to one per REBUILD_INTERVAL_MS per client;\n * APP_GRANT_REVOKED is never retried (ensure itself reports it).\n * - `ignored` notes never fail a request. ensure never writes annotations, so\n * an edited name, `.describe()` or collection description comes back as\n * ANNOTATION_NOT_APPLIED; it is logged as a warning pointing at\n * metadata:updateOne for names, or schema:replace for schema annotations.\n */\nimport { createHash } from 'node:crypto';\nimport type { DataCall } from './call.js';\nimport { assertNoWriteErrors, MAX_ATOMIC_ITEMS } from './collection.js';\nimport type { CollectionDefinition } from './define.js';\nimport { ACCESS_REASONS, DataError } from './error.js';\nimport { compileCollection, validateDocument, type CompiledCollection } from './schema.js';\n\nexport type DataEnvironment = 'preview' | 'deployed';\n\nexport interface EnsureWarning {\n code: string;\n path?: string;\n message?: string;\n}\n\nexport interface EnsureNote {\n path: string;\n reason?: string;\n message?: string;\n}\n\nexport interface EnsureResult {\n alias: string;\n collectionId: string;\n revision: number;\n status: 'created' | 'unchanged' | 'widened';\n ignored?: EnsureNote[];\n warnings?: EnsureWarning[];\n indexStatus?: unknown[];\n}\n\nexport interface EnsureConflict {\n alias: string;\n collectionId?: string;\n path?: string;\n reason?: string;\n current?: string;\n declared?: string;\n}\n\nexport interface EnsureState {\n appId?: string;\n results: EnsureResult[];\n /** Lower-cased alias → collection ID. */\n collectionIds: Map<string, string>;\n /** Declarations that conflicted in a deployment (served with their existing ID, if any). */\n conflicts: EnsureConflict[];\n}\n\nexport interface Logger {\n info(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n}\n\nexport interface BootstrapConfig {\n call: DataCall;\n collections: readonly CollectionDefinition[];\n environment: DataEnvironment;\n logger: Logger;\n}\n\nconst SEED_ATTEMPTS = 3;\n/** Wait before replaying seed chunk attempt n+1: n × this. */\nexport const SEED_RETRY_MS = 1_000;\n\n/** At most one self-healing rebuild per client in this window. */\nexport const REBUILD_INTERVAL_MS = 30_000;\n\n/**\n * Whether a record call failed because the collection ID it used is gone or\n * no longer granted, by UNS's stable `data.reason` code. Archive and Preview\n * purge also remove the App grant, so most stale IDs answer\n * COLLECTION_NOT_GRANTED or COLLECTION_NOT_FOUND. APP_PERMISSION_MISSING (the\n * key lacks e.g. `uns.delete`) and APP_GRANT_REVOKED are not stale IDs.\n */\nexport function isStaleCollectionError(error: unknown): boolean {\n return (\n error instanceof DataError &&\n (error.reason === ACCESS_REASONS.notGranted || error.reason === ACCESS_REASONS.notFound)\n );\n}\n\nfunction sameCollectionIds(a: EnsureState, b: EnsureState): boolean {\n if (a.collectionIds.size !== b.collectionIds.size) return false;\n for (const [alias, id] of a.collectionIds) {\n if (b.collectionIds.get(alias) !== id) return false;\n }\n return true;\n}\n\n/** Idempotency key of one seed chunk (UNS keys are at most 96 characters). */\nfunction seedChunkKey(collectionId: string, chunk: number): string {\n return `seed-${createHash('sha256').update(collectionId).digest('hex').slice(0, 40)}-${chunk}`;\n}\n\n/** What to do about each SCHEMA_CONFLICT reason (CloudAppCollectionConflict.reason). */\nconst CONFLICT_HINTS: Record<string, string> = {\n TYPE_CONFLICT: \"a field's type cannot change; use a new field name and backfill with updateMany\",\n LIMIT_EXCEEDED: 'the joined schema exceeds a UNS limit (depth, properties, enum values or indexes); split the structure',\n OPEN_OBJECT: 'every object must be closed; declare it with z.object',\n ALIAS_IN_USE: 'the alias belongs to another collection; pick another alias',\n NAME_IN_USE: 'the business name belongs to another collection in this folder; pick another name and keep the stable alias',\n INVALID_INDEX: 'fix the index declaration',\n JOIN_UNSUPPORTED:\n 'the stored schema holds a node the declaration cannot widen (e.g. enum values outside its range); repair it with schema:replace via the tier0 MCP',\n DATA_RULE_FIELD:\n 'an employee data rule (ownerField / stateField) uses this field; keep it required with the same type, or ask a workspace admin to change the rule',\n};\n\nfunction describeConflicts(conflicts: EnsureConflict[]): string {\n return conflicts\n .map((conflict) => {\n const where = `${conflict.alias}${conflict.path ? `.${conflict.path}` : ''}`;\n const types = conflict.current || conflict.declared ? ` (stored ${conflict.current ?? '?'}, declared ${conflict.declared ?? '?'})` : '';\n const hint = conflict.reason && CONFLICT_HINTS[conflict.reason] ? ` — ${CONFLICT_HINTS[conflict.reason]}` : '';\n return ` - ${where}: ${conflict.reason ?? 'conflict'}${types}${hint}`;\n })\n .join('\\n');\n}\n\nfunction notePath(alias: string, note: EnsureNote): string {\n return note.path ? `${alias}.${note.path}` : alias;\n}\n\nfunction describeWarnings(results: EnsureResult[]): string {\n return results\n .flatMap((result) =>\n (result.warnings ?? []).map(\n (warning) => ` - ${result.alias}${warning.path ? `.${warning.path}` : ''}: ${warning.code}${warning.message ? ` — ${warning.message}` : ''}`,\n ),\n )\n .join('\\n');\n}\n\nexport function createBootstrap(config: BootstrapConfig) {\n const { call, collections, environment, logger } = config;\n let pending: Promise<EnsureState> | null = null;\n let lastRebuild = Number.NEGATIVE_INFINITY;\n\n async function requestEnsure(items: CompiledCollection[]) {\n // ensure is App-level work: it never carries the employee data subject.\n return call<{ appId?: string; results: EnsureResult[] }>('appCollectionsEnsure', { collections: items });\n }\n\n async function insertSeedChunk(collectionId: string, chunk: number, documents: { id?: string; data: Record<string, unknown> }[]) {\n for (let attempt = 1; ; attempt += 1) {\n try {\n const result = await call<{ writeErrors?: Record<string, unknown>[] }>('recordBulkWrite', {\n collectionId,\n operations: documents.map(document => ({ insertOne: document })),\n ordered: true,\n atomic: true,\n idempotencyKey: seedChunkKey(collectionId, chunk),\n });\n assertNoWriteErrors(result, 'seed');\n return;\n } catch (error) {\n // The chunk key is stable, so replaying is safe even when the outcome is unknown: a chunk\n // that did commit replays its receipt. Wait first, so a write still running can finish.\n if (!(error instanceof DataError) || !(error.outcomeUnknown || error.retry.safe) || attempt >= SEED_ATTEMPTS) throw error;\n await new Promise((resolve) => setTimeout(resolve, SEED_RETRY_MS * attempt));\n }\n }\n }\n\n async function writeSeeds(results: EnsureResult[]) {\n for (const result of results) {\n if (result.status !== 'created') continue;\n const definition = collections.find((candidate) => candidate.alias.toLowerCase() === result.alias.toLowerCase());\n const seed = definition?.seed;\n if (!definition || !seed || seed.length === 0) continue;\n try {\n const documents = seed.map((document) => {\n const { id, data } = validateDocument(definition, document as Record<string, unknown>);\n return { id, data };\n });\n for (let start = 0; start < documents.length; start += MAX_ATOMIC_ITEMS) {\n await insertSeedChunk(result.collectionId, start / MAX_ATOMIC_ITEMS, documents.slice(start, start + MAX_ATOMIC_ITEMS));\n }\n logger.info(`[data] seeded ${documents.length} record(s) into \"${result.alias}\"`);\n } catch (error) {\n // The collection exists now; a later ensure reports \"unchanged\" and\n // never re-seeds, so the failure must be visible in the server log.\n logger.error(`[data] seed for new collection \"${result.alias}\" failed; it keeps the chunks written so far:`, error);\n }\n }\n }\n\n async function run(payload: CompiledCollection[]): Promise<EnsureState> {\n const conflicts: EnsureConflict[] = [];\n let remaining = payload;\n let response: { appId?: string; results: EnsureResult[] } = { results: [] };\n while (remaining.length > 0) {\n try {\n response = await requestEnsure(remaining);\n break;\n } catch (error) {\n if (!(error instanceof DataError) || error.code !== 'SCHEMA_CONFLICT') throw error;\n const reported = Array.isArray(error.details.conflicts) ? (error.details.conflicts as EnsureConflict[]) : [];\n const summary = describeConflicts(reported);\n if (environment === 'preview') {\n throw new DataError({\n message:\n `The collection declarations conflict with the stored collection schemas; nothing was changed:\\n${summary}`,\n status: 409,\n code: 'SCHEMA_CONFLICT',\n upstreamStatus: error.upstreamStatus,\n requestId: error.requestId,\n execution: error.execution,\n attempts: error.attempts,\n details: error.details,\n });\n }\n // A deployment keeps serving: drop the conflicting declarations (the\n // whole batch was rejected) and ensure the rest again.\n const conflicting = new Set(reported.map((conflict) => conflict.alias.toLowerCase()));\n const next = remaining.filter((item) => !conflicting.has(item.alias.toLowerCase()));\n if (next.length === remaining.length) throw error;\n logger.error(`[data] ensure: declarations conflict with stored schemas; serving them unchanged:\\n${summary}`);\n conflicts.push(...reported);\n remaining = next;\n }\n }\n\n const results = response.results ?? [];\n const collectionIds = new Map<string, string>();\n for (const conflict of conflicts) {\n if (conflict.collectionId) collectionIds.set(conflict.alias.toLowerCase(), conflict.collectionId);\n }\n for (const result of results) {\n collectionIds.set(result.alias.toLowerCase(), result.collectionId);\n const notes = result.ignored ?? [];\n const annotations = notes.filter((note) => note.reason === 'ANNOTATION_NOT_APPLIED');\n const directories = notes.filter((note) => note.reason === 'DIRECTORY_PATH_NOT_APPLIED');\n const wider = notes.filter((note) => note.reason !== 'ANNOTATION_NOT_APPLIED' && note.reason !== 'DIRECTORY_PATH_NOT_APPLIED');\n if (directories.length > 0) {\n logger.warn(\n `[data] ensure keeps existing collection locations; not applied: ${directories.map((note) => notePath(result.alias, note)).join(', ')}. ` +\n 'A directoryPath declaration only places a new collection. Move existing collections explicitly through metadata operations when authorized.',\n );\n }\n if (wider.length > 0) {\n logger.info(\n `[data] \"${result.alias}\" storage is wider than this declaration (or has retired parts); ignored: ` +\n wider.map((note) => `${note.path || '(root)'} ${note.reason ?? ''}`.trim()).join(', '),\n );\n }\n if (annotations.length > 0) {\n // A hint, not an error: storage keeps its annotations and serves as before.\n logger.warn(\n `[data] ensure does not change stored names/titles/descriptions; not applied: ${annotations.map((note) => notePath(result.alias, note)).join(', ')}. ` +\n `Rename with metadata:updateOne via the tier0 MCP; apply schema annotations with schema:replace, selecting alias, recordSchema, indexes and description from compileCollection(...).`,\n );\n }\n }\n\n await writeSeeds(results);\n\n const warnings = describeWarnings(results);\n if (warnings) {\n if (environment === 'preview') {\n throw new DataError({\n message:\n `Collections were ensured with warnings:\\n${warnings}\\n` +\n 'REQUIRED_NOT_ENFORCED: make the field optional again or narrow explicitly with schema:replace via the tier0 MCP. ' +\n 'INDEX_BUILD_FAILED: fix the duplicate or invalid data, then the next ensure retries the index.',\n status: 500,\n code: 'SCHEMA_WARNINGS',\n // ensure did apply; only the warnings fail the Preview request.\n execution: 'committed',\n details: { results },\n });\n }\n logger.warn(`[data] ensure warnings:\\n${warnings}`);\n }\n\n return { appId: response.appId, results, collectionIds, conflicts };\n }\n\n /** Ensures every declaration once per client; a failure is forgotten so the next call retries. */\n function ensure(): Promise<EnsureState> {\n pending ??= Promise.resolve()\n .then(() => run(collections.map(compileCollection)))\n .catch((error) => {\n pending = null;\n throw error;\n });\n return pending;\n }\n\n /**\n * Re-ensures after `before` turned out stale. Joins a rebuild already in\n * flight; otherwise rebuilds at most once per REBUILD_INTERVAL_MS. Resolves\n * whether any collection ID changed; ensure errors (APP_GRANT_REVOKED, …)\n * propagate.\n */\n async function rebuild(before: EnsureState, cause: DataError): Promise<boolean> {\n // Only owned IDs can be recovered by ensure; shared references must keep their original error.\n const failedId = cause.details.collectionId;\n if (typeof failedId === 'string' && ![...before.collectionIds.values()].includes(failedId)) return false;\n const current = ensure();\n const latest = await current;\n if (latest !== before) return !sameCollectionIds(before, latest);\n if (pending !== current) return !sameCollectionIds(before, await ensure());\n const now = Date.now();\n if (now - lastRebuild < REBUILD_INTERVAL_MS) return false;\n lastRebuild = now;\n logger.warn(`[data] a collection ID is no longer usable (${cause.code}: ${cause.message}); ensuring collections again`);\n pending = null;\n return !sameCollectionIds(before, await ensure());\n }\n\n /**\n * Runs one data call; when it fails on a stale collection ID, rebuilds and\n * runs it once more if an ID changed. `retry: false` (calls continuing a\n * cursor or resumeAfter token of the old collection) only rebuilds.\n */\n async function recover<R>(fn: () => Promise<R>, options: { retry?: boolean } = {}): Promise<R> {\n const before = await ensure();\n try {\n return await fn();\n } catch (error) {\n if (!isStaleCollectionError(error)) throw error;\n const changed = await rebuild(before, error as DataError);\n if (!changed || options.retry === false) throw error;\n return fn();\n }\n }\n\n async function resolve(definition: CollectionDefinition): Promise<string> {\n const state = await ensure();\n const id = state.collectionIds.get(definition.alias.toLowerCase());\n if (!id) {\n throw new DataError({\n message: `Collection \"${definition.alias}\" is unavailable: ensure did not return it (see the server log).`,\n status: 503,\n code: 'COLLECTION_UNAVAILABLE',\n });\n }\n return id;\n }\n\n return { ensure, resolve, recover, rebuild };\n}\n"]}
@@ -18,6 +18,8 @@ export declare const MAX_COLLECTIONS = 64;
18
18
  export declare const MAX_DESCRIPTION_LENGTH = 512;
19
19
  /** UNS: business-facing collection name length in Unicode characters. */
20
20
  export declare const MAX_NAME_LENGTH = 63;
21
+ /** Business directory paths may omit unknown ISA-95 levels. */
22
+ export declare const MAX_DIRECTORY_DEPTH = 16;
21
23
  /** Seeds are inserted in atomic chunks of 200 during the first request; keep them a baseline, not a data import. */
22
24
  export declare const MAX_SEED_DOCUMENTS = 1000;
23
25
  /** Same shape as collection metadata indexes, limited to record indexes. */
@@ -53,6 +55,8 @@ export interface CollectionDefinition<S extends CollectionSchema = CollectionSch
53
55
  readonly alias: string;
54
56
  /** Business-facing name, independent of the stable App alias. */
55
57
  readonly name: string;
58
+ /** Workspace-root business path. Required when creating a new collection; omitted only for existing aliases. */
59
+ readonly directoryPath?: readonly string[];
56
60
  /** Zod 4 object schema of the record body (no `_id` / `_meta`). */
57
61
  readonly schema: S;
58
62
  readonly indexes: readonly IndexSpec[];
@@ -82,9 +86,12 @@ export type NewDoc<C extends CollectionDefinition> = z.input<C['schema']> & {
82
86
  export declare function defineCollection<S extends CollectionSchema>(definition: {
83
87
  alias: string;
84
88
  name: string;
89
+ directoryPath?: readonly string[];
85
90
  schema: S;
86
91
  indexes?: IndexSpec[];
87
92
  description?: string;
88
93
  seed?: SeedDoc<S>[];
89
94
  }): CollectionDefinition<S>;
90
95
  export declare function assertCollectionName(name: unknown): asserts name is string;
96
+ /** Validate each business name as one segment; no normalization or fabricated levels. */
97
+ export declare function assertDirectoryPath(path: unknown): asserts path is readonly string[];
@@ -6,6 +6,8 @@ export const MAX_COLLECTIONS = 64;
6
6
  export const MAX_DESCRIPTION_LENGTH = 512;
7
7
  /** UNS: business-facing collection name length in Unicode characters. */
8
8
  export const MAX_NAME_LENGTH = 63;
9
+ /** Business directory paths may omit unknown ISA-95 levels. */
10
+ export const MAX_DIRECTORY_DEPTH = 16;
9
11
  /** Seeds are inserted in atomic chunks of 200 during the first request; keep them a baseline, not a data import. */
10
12
  export const MAX_SEED_DOCUMENTS = 1000;
11
13
  export function collectionLabel(target) {
@@ -16,6 +18,8 @@ export function defineCollection(definition) {
16
18
  throw new Error(`Collection alias "${definition.alias}" must match ${ALIAS_PATTERN} (letters, digits, "_" or "-", starting with a letter).`);
17
19
  }
18
20
  assertCollectionName(definition.name);
21
+ if (definition.directoryPath !== undefined)
22
+ assertDirectoryPath(definition.directoryPath);
19
23
  if (definition.description && [...definition.description].length > MAX_DESCRIPTION_LENGTH) {
20
24
  throw new Error(`Collection "${definition.alias}": description is longer than ${MAX_DESCRIPTION_LENGTH} characters.`);
21
25
  }
@@ -25,6 +29,7 @@ export function defineCollection(definition) {
25
29
  return Object.freeze({
26
30
  alias: definition.alias,
27
31
  name: definition.name,
32
+ ...(definition.directoryPath !== undefined ? { directoryPath: Object.freeze([...definition.directoryPath]) } : {}),
28
33
  schema: definition.schema,
29
34
  indexes: Object.freeze([...(definition.indexes ?? [])]),
30
35
  ...(definition.description ? { description: definition.description } : {}),
@@ -36,4 +41,18 @@ export function assertCollectionName(name) {
36
41
  throw new Error(`Collection name must be nonempty, at most ${MAX_NAME_LENGTH} Unicode characters, without surrounding whitespace, "/" or NUL.`);
37
42
  }
38
43
  }
44
+ /** Validate each business name as one segment; no normalization or fabricated levels. */
45
+ export function assertDirectoryPath(path) {
46
+ if (!Array.isArray(path) || path.length < 1 || path.length > MAX_DIRECTORY_DEPTH) {
47
+ throw new Error(`directoryPath must contain 1–${MAX_DIRECTORY_DEPTH} business directory names from the workspace root.`);
48
+ }
49
+ for (let index = 0; index < path.length; index += 1) {
50
+ try {
51
+ assertCollectionName(path[index]);
52
+ }
53
+ catch {
54
+ throw new Error(`directoryPath[${index}] must be a nonempty business name of at most ${MAX_NAME_LENGTH} Unicode characters, without surrounding whitespace, "/" or NUL.`);
55
+ }
56
+ }
57
+ }
39
58
  //# sourceMappingURL=define.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"define.js","sourceRoot":"","sources":["../../../src/data/define.ts"],"names":[],"mappings":"AAaA,0DAA0D;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAG,+BAA+B,CAAC;AAC7D,uFAAuF;AACvF,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAClC,wDAAwD;AACxD,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAC1C,yEAAyE;AACzE,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAClC,oHAAoH;AACpH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAwDvC,MAAM,UAAU,eAAe,CAAC,MAAwB;IACtD,OAAO,cAAc,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AACvE,CAAC;AAaD,MAAM,UAAU,gBAAgB,CAA6B,UAO5D;IACC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,qBAAqB,UAAU,CAAC,KAAK,gBAAgB,aAAa,yDAAyD,CAC5H,CAAC;IACJ,CAAC;IACD,oBAAoB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,UAAU,CAAC,WAAW,IAAI,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,sBAAsB,EAAE,CAAC;QAC1F,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,CAAC,KAAK,iCAAiC,sBAAsB,cAAc,CAAC,CAAC;IACxH,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CACb,eAAe,UAAU,CAAC,KAAK,cAAc,kBAAkB,wBAAwB,UAAU,CAAC,IAAI,CAAC,MAAM,iEAAiE,CAC/K,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;QACvD,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAa;IAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,GAAG,eAAe,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvI,MAAM,IAAI,KAAK,CAAC,6CAA6C,eAAe,kEAAkE,CAAC,CAAC;IAClJ,CAAC;AACH,CAAC","sourcesContent":["/**\n * Collection declarations — the single source of truth for App data.\n *\n * An App declares every collection with `defineCollection(...)` and passes the\n * list to `createDataClient({ collections })`. The client ensures that list in\n * one batch on first data access: a missing collection is created, a\n * declaration wider than storage widens it, and nothing is ever narrowed.\n *\n * This module is pure (Zod types only) so declarations, API input schemas and\n * build-time checks can import it without pulling in the runtime client.\n */\nimport type { z } from 'zod';\n\n/** Collection alias: unique per App, case-insensitive. */\nexport const ALIAS_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,62}$/;\n/** UNS: one ensure takes 1–64 declarations, and an App owns at most 64 collections. */\nexport const MAX_COLLECTIONS = 64;\n/** UNS: collection description length in characters. */\nexport const MAX_DESCRIPTION_LENGTH = 512;\n/** UNS: business-facing collection name length in Unicode characters. */\nexport const MAX_NAME_LENGTH = 63;\n/** Seeds are inserted in atomic chunks of 200 during the first request; keep them a baseline, not a data import. */\nexport const MAX_SEED_DOCUMENTS = 1000;\n\n/** Same shape as collection metadata indexes, limited to record indexes. */\nexport interface IndexSpec {\n /** Business field path without `data.`, e.g. `code` or `customer.id`. */\n path?: string;\n /** Compound index, at most 3 paths. Mutually exclusive with `path`. */\n paths?: string[];\n unique?: boolean;\n /** `btree` (default) or `gin` for one object/array path; GIN cannot be unique. */\n kind?: 'btree' | 'gin';\n /**\n * TTL index: UNS physically deletes a record this many seconds\n * (60–31536000) after the instant in `path`, an integer field of Unix\n * milliseconds. At most one per collection, on a single non-unique `path`. Expired\n * records cannot be restored. ensure may add a TTL or lengthen it;\n * shortening or removing it takes schema:replace.\n */\n expireAfterSeconds?: number;\n}\n\n/** System metadata of a stored record. Times are Unix milliseconds. */\nexport interface RecordMeta {\n revision: number;\n createdAt: number;\n updatedAt: number;\n}\n\nexport type CollectionSchema = z.ZodObject;\n\n/** A seed document: a full record plus the fixed `_id` it is inserted with. */\nexport type SeedDoc<S extends CollectionSchema> = z.input<S> & { _id: string };\n\nexport interface CollectionDefinition<S extends CollectionSchema = CollectionSchema> {\n readonly alias: string;\n /** Business-facing name, independent of the stable App alias. */\n readonly name: string;\n /** Zod 4 object schema of the record body (no `_id` / `_meta`). */\n readonly schema: S;\n readonly indexes: readonly IndexSpec[];\n readonly description?: string;\n /**\n * Baseline records, written only when ensure reports this collection as\n * `created`. Never re-applied to an existing collection.\n */\n readonly seed?: readonly SeedDoc<S>[];\n}\n\n/** An existing collection. The optional schema validates writes locally; it never changes storage. */\nexport interface CollectionReference<S extends CollectionSchema = CollectionSchema> {\n readonly collectionId: string;\n readonly schema?: S;\n}\n\nexport type CollectionTarget = CollectionDefinition | CollectionReference;\n\nexport function collectionLabel(target: CollectionTarget): string {\n return 'collectionId' in target ? target.collectionId : target.alias;\n}\n\n/** A stored record as services read it: `{ _id, ...fields, _meta }`. */\nexport type Doc<C extends CollectionDefinition> = z.output<C['schema']> & {\n _id: string;\n _meta: RecordMeta;\n};\n\n/** A record to insert: the schema input plus an optional caller-chosen `_id`. */\nexport type NewDoc<C extends CollectionDefinition> = z.input<C['schema']> & {\n _id?: string;\n};\n\nexport function defineCollection<S extends CollectionSchema>(definition: {\n alias: string;\n name: string;\n schema: S;\n indexes?: IndexSpec[];\n description?: string;\n seed?: SeedDoc<S>[];\n}): CollectionDefinition<S> {\n if (!ALIAS_PATTERN.test(definition.alias)) {\n throw new Error(\n `Collection alias \"${definition.alias}\" must match ${ALIAS_PATTERN} (letters, digits, \"_\" or \"-\", starting with a letter).`,\n );\n }\n assertCollectionName(definition.name);\n if (definition.description && [...definition.description].length > MAX_DESCRIPTION_LENGTH) {\n throw new Error(`Collection \"${definition.alias}\": description is longer than ${MAX_DESCRIPTION_LENGTH} characters.`);\n }\n if (definition.seed && definition.seed.length > MAX_SEED_DOCUMENTS) {\n throw new Error(\n `Collection \"${definition.alias}\": at most ${MAX_SEED_DOCUMENTS} seed documents (got ${definition.seed.length}). Seeds are a baseline written on creation, not a bulk import.`,\n );\n }\n return Object.freeze({\n alias: definition.alias,\n name: definition.name,\n schema: definition.schema,\n indexes: Object.freeze([...(definition.indexes ?? [])]),\n ...(definition.description ? { description: definition.description } : {}),\n ...(definition.seed ? { seed: Object.freeze([...definition.seed]) } : {}),\n });\n}\n\nexport function assertCollectionName(name: unknown): asserts name is string {\n if (typeof name !== 'string' || name.length === 0 || name.trim() !== name || [...name].length > MAX_NAME_LENGTH || /[\\/\\0]/.test(name)) {\n throw new Error(`Collection name must be nonempty, at most ${MAX_NAME_LENGTH} Unicode characters, without surrounding whitespace, \"/\" or NUL.`);\n }\n}\n"]}
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../../../src/data/define.ts"],"names":[],"mappings":"AAaA,0DAA0D;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAG,+BAA+B,CAAC;AAC7D,uFAAuF;AACvF,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAClC,wDAAwD;AACxD,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAC1C,yEAAyE;AACzE,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAClC,+DAA+D;AAC/D,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AACtC,oHAAoH;AACpH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AA0DvC,MAAM,UAAU,eAAe,CAAC,MAAwB;IACtD,OAAO,cAAc,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AACvE,CAAC;AAaD,MAAM,UAAU,gBAAgB,CAA6B,UAQ5D;IACC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,qBAAqB,UAAU,CAAC,KAAK,gBAAgB,aAAa,yDAAyD,CAC5H,CAAC;IACJ,CAAC;IACD,oBAAoB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,UAAU,CAAC,aAAa,KAAK,SAAS;QAAE,mBAAmB,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAC1F,IAAI,UAAU,CAAC,WAAW,IAAI,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,sBAAsB,EAAE,CAAC;QAC1F,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,CAAC,KAAK,iCAAiC,sBAAsB,cAAc,CAAC,CAAC;IACxH,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CACb,eAAe,UAAU,CAAC,KAAK,cAAc,kBAAkB,wBAAwB,UAAU,CAAC,IAAI,CAAC,MAAM,iEAAiE,CAC/K,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,GAAG,CAAC,UAAU,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClH,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;QACvD,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAa;IAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,GAAG,eAAe,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvI,MAAM,IAAI,KAAK,CAAC,6CAA6C,eAAe,kEAAkE,CAAC,CAAC;IAClJ,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,mBAAmB,CAAC,IAAa;IAC/C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CAAC,gCAAgC,mBAAmB,oDAAoD,CAAC,CAAC;IAC3H,CAAC;IACD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,iBAAiB,KAAK,iDAAiD,eAAe,kEAAkE,CAAC,CAAC;QAC5K,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["/**\n * Collection declarations — the single source of truth for App data.\n *\n * An App declares every collection with `defineCollection(...)` and passes the\n * list to `createDataClient({ collections })`. The client ensures that list in\n * one batch on first data access: a missing collection is created, a\n * declaration wider than storage widens it, and nothing is ever narrowed.\n *\n * This module is pure (Zod types only) so declarations, API input schemas and\n * build-time checks can import it without pulling in the runtime client.\n */\nimport type { z } from 'zod';\n\n/** Collection alias: unique per App, case-insensitive. */\nexport const ALIAS_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,62}$/;\n/** UNS: one ensure takes 1–64 declarations, and an App owns at most 64 collections. */\nexport const MAX_COLLECTIONS = 64;\n/** UNS: collection description length in characters. */\nexport const MAX_DESCRIPTION_LENGTH = 512;\n/** UNS: business-facing collection name length in Unicode characters. */\nexport const MAX_NAME_LENGTH = 63;\n/** Business directory paths may omit unknown ISA-95 levels. */\nexport const MAX_DIRECTORY_DEPTH = 16;\n/** Seeds are inserted in atomic chunks of 200 during the first request; keep them a baseline, not a data import. */\nexport const MAX_SEED_DOCUMENTS = 1000;\n\n/** Same shape as collection metadata indexes, limited to record indexes. */\nexport interface IndexSpec {\n /** Business field path without `data.`, e.g. `code` or `customer.id`. */\n path?: string;\n /** Compound index, at most 3 paths. Mutually exclusive with `path`. */\n paths?: string[];\n unique?: boolean;\n /** `btree` (default) or `gin` for one object/array path; GIN cannot be unique. */\n kind?: 'btree' | 'gin';\n /**\n * TTL index: UNS physically deletes a record this many seconds\n * (60–31536000) after the instant in `path`, an integer field of Unix\n * milliseconds. At most one per collection, on a single non-unique `path`. Expired\n * records cannot be restored. ensure may add a TTL or lengthen it;\n * shortening or removing it takes schema:replace.\n */\n expireAfterSeconds?: number;\n}\n\n/** System metadata of a stored record. Times are Unix milliseconds. */\nexport interface RecordMeta {\n revision: number;\n createdAt: number;\n updatedAt: number;\n}\n\nexport type CollectionSchema = z.ZodObject;\n\n/** A seed document: a full record plus the fixed `_id` it is inserted with. */\nexport type SeedDoc<S extends CollectionSchema> = z.input<S> & { _id: string };\n\nexport interface CollectionDefinition<S extends CollectionSchema = CollectionSchema> {\n readonly alias: string;\n /** Business-facing name, independent of the stable App alias. */\n readonly name: string;\n /** Workspace-root business path. Required when creating a new collection; omitted only for existing aliases. */\n readonly directoryPath?: readonly string[];\n /** Zod 4 object schema of the record body (no `_id` / `_meta`). */\n readonly schema: S;\n readonly indexes: readonly IndexSpec[];\n readonly description?: string;\n /**\n * Baseline records, written only when ensure reports this collection as\n * `created`. Never re-applied to an existing collection.\n */\n readonly seed?: readonly SeedDoc<S>[];\n}\n\n/** An existing collection. The optional schema validates writes locally; it never changes storage. */\nexport interface CollectionReference<S extends CollectionSchema = CollectionSchema> {\n readonly collectionId: string;\n readonly schema?: S;\n}\n\nexport type CollectionTarget = CollectionDefinition | CollectionReference;\n\nexport function collectionLabel(target: CollectionTarget): string {\n return 'collectionId' in target ? target.collectionId : target.alias;\n}\n\n/** A stored record as services read it: `{ _id, ...fields, _meta }`. */\nexport type Doc<C extends CollectionDefinition> = z.output<C['schema']> & {\n _id: string;\n _meta: RecordMeta;\n};\n\n/** A record to insert: the schema input plus an optional caller-chosen `_id`. */\nexport type NewDoc<C extends CollectionDefinition> = z.input<C['schema']> & {\n _id?: string;\n};\n\nexport function defineCollection<S extends CollectionSchema>(definition: {\n alias: string;\n name: string;\n directoryPath?: readonly string[];\n schema: S;\n indexes?: IndexSpec[];\n description?: string;\n seed?: SeedDoc<S>[];\n}): CollectionDefinition<S> {\n if (!ALIAS_PATTERN.test(definition.alias)) {\n throw new Error(\n `Collection alias \"${definition.alias}\" must match ${ALIAS_PATTERN} (letters, digits, \"_\" or \"-\", starting with a letter).`,\n );\n }\n assertCollectionName(definition.name);\n if (definition.directoryPath !== undefined) assertDirectoryPath(definition.directoryPath);\n if (definition.description && [...definition.description].length > MAX_DESCRIPTION_LENGTH) {\n throw new Error(`Collection \"${definition.alias}\": description is longer than ${MAX_DESCRIPTION_LENGTH} characters.`);\n }\n if (definition.seed && definition.seed.length > MAX_SEED_DOCUMENTS) {\n throw new Error(\n `Collection \"${definition.alias}\": at most ${MAX_SEED_DOCUMENTS} seed documents (got ${definition.seed.length}). Seeds are a baseline written on creation, not a bulk import.`,\n );\n }\n return Object.freeze({\n alias: definition.alias,\n name: definition.name,\n ...(definition.directoryPath !== undefined ? { directoryPath: Object.freeze([...definition.directoryPath]) } : {}),\n schema: definition.schema,\n indexes: Object.freeze([...(definition.indexes ?? [])]),\n ...(definition.description ? { description: definition.description } : {}),\n ...(definition.seed ? { seed: Object.freeze([...definition.seed]) } : {}),\n });\n}\n\nexport function assertCollectionName(name: unknown): asserts name is string {\n if (typeof name !== 'string' || name.length === 0 || name.trim() !== name || [...name].length > MAX_NAME_LENGTH || /[\\/\\0]/.test(name)) {\n throw new Error(`Collection name must be nonempty, at most ${MAX_NAME_LENGTH} Unicode characters, without surrounding whitespace, \"/\" or NUL.`);\n }\n}\n\n/** Validate each business name as one segment; no normalization or fabricated levels. */\nexport function assertDirectoryPath(path: unknown): asserts path is readonly string[] {\n if (!Array.isArray(path) || path.length < 1 || path.length > MAX_DIRECTORY_DEPTH) {\n throw new Error(`directoryPath must contain 1–${MAX_DIRECTORY_DEPTH} business directory names from the workspace root.`);\n }\n for (let index = 0; index < path.length; index += 1) {\n try {\n assertCollectionName(path[index]);\n } catch {\n throw new Error(`directoryPath[${index}] must be a nonempty business name of at most ${MAX_NAME_LENGTH} Unicode characters, without surrounding whitespace, \"/\" or NUL.`);\n }\n }\n}\n"]}
@@ -38,6 +38,7 @@ export interface NormalizedIndex {
38
38
  export interface CompiledCollection {
39
39
  alias: string;
40
40
  name: string;
41
+ directoryPath?: readonly string[];
41
42
  recordSchema: RecordSchema;
42
43
  indexes: NormalizedIndex[];
43
44
  description?: string;
@@ -10,7 +10,7 @@
10
10
  * time) instead of on the first request.
11
11
  */
12
12
  import { z } from 'zod';
13
- import { ALIAS_PATTERN, assertCollectionName, collectionLabel } from './define.js';
13
+ import { ALIAS_PATTERN, assertCollectionName, assertDirectoryPath, collectionLabel } from './define.js';
14
14
  export class CollectionSchemaError extends Error {
15
15
  alias;
16
16
  issues;
@@ -466,6 +466,14 @@ export function compileCollection(definition) {
466
466
  catch (error) {
467
467
  throw new CollectionSchemaError(definition.alias, [{ path: 'name', message: error instanceof Error ? error.message : String(error) }]);
468
468
  }
469
+ if (definition.directoryPath !== undefined) {
470
+ try {
471
+ assertDirectoryPath(definition.directoryPath);
472
+ }
473
+ catch (error) {
474
+ throw new CollectionSchemaError(definition.alias, [{ path: 'directoryPath', message: error instanceof Error ? error.message : String(error) }]);
475
+ }
476
+ }
469
477
  const recordSchema = toRecordSchema(definition.alias, definition.schema);
470
478
  const issues = [];
471
479
  const indexes = normalizeIndexes(definition.alias, definition.indexes, recordSchema, issues);
@@ -474,6 +482,7 @@ export function compileCollection(definition) {
474
482
  const result = {
475
483
  alias: definition.alias,
476
484
  name: definition.name,
485
+ ...(definition.directoryPath !== undefined ? { directoryPath: Object.freeze([...definition.directoryPath]) } : {}),
477
486
  recordSchema,
478
487
  indexes,
479
488
  ...(definition.description ? { description: definition.description } : {}),