@devtrack-solution/codesdd 1.2.4-rc3 → 1.2.4

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 (128) hide show
  1. package/.sdd/skills/curated/devtrack-api/SKILL.md +91 -12
  2. package/.sdd/skills/curated/devtrack-api/agents/claude-code.yaml +2 -0
  3. package/.sdd/skills/curated/devtrack-api/agents/codex.yaml +2 -0
  4. package/.sdd/skills/curated/devtrack-api/agents/cursor.yaml +2 -0
  5. package/.sdd/skills/curated/devtrack-api/agents/gemini.yaml +2 -0
  6. package/.sdd/skills/curated/devtrack-api/agents/kimi.yaml +2 -0
  7. package/.sdd/skills/curated/devtrack-api/agents/openai.yaml +3 -3
  8. package/.sdd/skills/curated/devtrack-api/agents/opencode.yaml +2 -0
  9. package/.sdd/skills/curated/devtrack-api/references/application-presentation.md +59 -3
  10. package/.sdd/skills/curated/devtrack-api/references/consumer-sync-policy.md +15 -3
  11. package/.sdd/skills/curated/devtrack-api/references/contract-pack.yaml +1898 -2
  12. package/.sdd/skills/curated/devtrack-api/references/domain-modeling.md +3 -1
  13. package/.sdd/skills/curated/devtrack-api/references/field-validation-protocol.md +40 -0
  14. package/.sdd/skills/curated/devtrack-api/references/foundation-layout.md +20 -2
  15. package/.sdd/skills/curated/devtrack-api/references/generated-artifact-invalidation.md +97 -0
  16. package/.sdd/skills/curated/devtrack-api/references/implementation-checklist.md +30 -1
  17. package/.sdd/skills/curated/devtrack-api/references/portable-agent-contract.md +4 -3
  18. package/.sdd/skills/curated/devtrack-api/references/testing-validation.md +22 -1
  19. package/.sdd/skills/curated/devtrack-api/references/typeorm-infrastructure.md +9 -5
  20. package/README.md +122 -25
  21. package/dist/cli/program.js +180 -11
  22. package/dist/commands/config.js +27 -1
  23. package/dist/commands/sdd/execution.js +64 -2
  24. package/dist/commands/sdd.js +119 -4
  25. package/dist/core/cli/command-matrix.d.ts +18 -0
  26. package/dist/core/cli/command-matrix.js +148 -0
  27. package/dist/core/cli-command-quality.js +2 -0
  28. package/dist/core/config-schema.d.ts +14 -1
  29. package/dist/core/config-schema.js +32 -1
  30. package/dist/core/config.d.ts +1 -0
  31. package/dist/core/config.js +11 -0
  32. package/dist/core/global-config.d.ts +13 -0
  33. package/dist/core/init.d.ts +2 -2
  34. package/dist/core/init.js +13 -14
  35. package/dist/core/sdd/agent-binding.d.ts +9 -9
  36. package/dist/core/sdd/agent-runtime-contract.d.ts +4 -4
  37. package/dist/core/sdd/allocator-recovery.d.ts +14 -0
  38. package/dist/core/sdd/allocator-recovery.js +30 -0
  39. package/dist/core/sdd/allocator-security.d.ts +18 -0
  40. package/dist/core/sdd/allocator-security.js +36 -0
  41. package/dist/core/sdd/api-foundation-baseline.d.ts +111 -0
  42. package/dist/core/sdd/api-foundation-baseline.js +151 -0
  43. package/dist/core/sdd/api-foundation-parity.d.ts +114 -0
  44. package/dist/core/sdd/api-foundation-parity.js +131 -0
  45. package/dist/core/sdd/api-profile-catalog.d.ts +36 -0
  46. package/dist/core/sdd/api-profile-catalog.js +132 -0
  47. package/dist/core/sdd/api-profile-dry-run-projection.d.ts +93 -0
  48. package/dist/core/sdd/api-profile-dry-run-projection.js +370 -0
  49. package/dist/core/sdd/api-profile-recipes.d.ts +82 -0
  50. package/dist/core/sdd/api-profile-recipes.js +484 -0
  51. package/dist/core/sdd/artifact-id-allocator.d.ts +368 -0
  52. package/dist/core/sdd/artifact-id-allocator.js +510 -0
  53. package/dist/core/sdd/check.d.ts +50 -1
  54. package/dist/core/sdd/check.js +286 -9
  55. package/dist/core/sdd/deepagent-contracts.d.ts +4 -4
  56. package/dist/core/sdd/deepagents/reversa-subagents.d.ts +3 -3
  57. package/dist/core/sdd/default-bootstrap-files.d.ts +1 -1
  58. package/dist/core/sdd/default-bootstrap-files.js +0 -2
  59. package/dist/core/sdd/default-skills.js +7 -5
  60. package/dist/core/sdd/devtrack-api-appliance.d.ts +34 -0
  61. package/dist/core/sdd/devtrack-api-appliance.js +138 -34
  62. package/dist/core/sdd/devtrack-api-architecture.d.ts +16 -0
  63. package/dist/core/sdd/devtrack-api-architecture.js +86 -0
  64. package/dist/core/sdd/docs-sync.js +3 -3
  65. package/dist/core/sdd/enterprise-mutating-command-gate.d.ts +27 -0
  66. package/dist/core/sdd/enterprise-mutating-command-gate.js +104 -0
  67. package/dist/core/sdd/enterprise-provenance-gates.d.ts +20 -0
  68. package/dist/core/sdd/enterprise-provenance-gates.js +63 -0
  69. package/dist/core/sdd/enterprise-provisioning-policy.d.ts +26 -0
  70. package/dist/core/sdd/enterprise-provisioning-policy.js +104 -0
  71. package/dist/core/sdd/governance-schemas.d.ts +2 -2
  72. package/dist/core/sdd/governance-schemas.js +11 -2
  73. package/dist/core/sdd/json-schema.js +4 -0
  74. package/dist/core/sdd/legacy-operations.js +93 -4
  75. package/dist/core/sdd/package-security-gates.js +2 -0
  76. package/dist/core/sdd/package-structure-gate.d.ts +85 -3
  77. package/dist/core/sdd/package-structure-gate.js +386 -8
  78. package/dist/core/sdd/parallel-feat-automation.d.ts +6 -6
  79. package/dist/core/sdd/plugin-policy.js +6 -1
  80. package/dist/core/sdd/plugin-registry.d.ts +3 -3
  81. package/dist/core/sdd/quality-validation.d.ts +5 -5
  82. package/dist/core/sdd/release-readiness.d.ts +49 -0
  83. package/dist/core/sdd/release-readiness.js +303 -8
  84. package/dist/core/sdd/reversa-architecture-extractor.d.ts +13 -0
  85. package/dist/core/sdd/reversa-architecture-extractor.js +89 -0
  86. package/dist/core/sdd/reversa-artifact-writer.d.ts +18 -0
  87. package/dist/core/sdd/reversa-artifact-writer.js +40 -0
  88. package/dist/core/sdd/reversa-command-policy.d.ts +136 -0
  89. package/dist/core/sdd/reversa-command-policy.js +361 -0
  90. package/dist/core/sdd/reversa-data-extractor.d.ts +11 -0
  91. package/dist/core/sdd/reversa-data-extractor.js +73 -0
  92. package/dist/core/sdd/reversa-equivalence.d.ts +20 -0
  93. package/dist/core/sdd/reversa-equivalence.js +34 -0
  94. package/dist/core/sdd/reversa-evidence.d.ts +298 -0
  95. package/dist/core/sdd/reversa-evidence.js +118 -0
  96. package/dist/core/sdd/reversa-reconstruction.d.ts +29 -0
  97. package/dist/core/sdd/reversa-reconstruction.js +32 -0
  98. package/dist/core/sdd/reversa-rules-extractor.d.ts +12 -0
  99. package/dist/core/sdd/reversa-rules-extractor.js +86 -0
  100. package/dist/core/sdd/reversa-source-safety.d.ts +19 -0
  101. package/dist/core/sdd/reversa-source-safety.js +105 -0
  102. package/dist/core/sdd/reversa-surface-scout.d.ts +13 -0
  103. package/dist/core/sdd/reversa-surface-scout.js +85 -0
  104. package/dist/core/sdd/reversa-ux-mapper.d.ts +11 -0
  105. package/dist/core/sdd/reversa-ux-mapper.js +73 -0
  106. package/dist/core/sdd/sdk-agent-plugin-quality-gates.d.ts +1 -1
  107. package/dist/core/sdd/services/archive-quality-coherence.service.d.ts +17 -0
  108. package/dist/core/sdd/services/archive-quality-coherence.service.js +141 -0
  109. package/dist/core/sdd/services/decide.service.js +1 -1
  110. package/dist/core/sdd/services/finalize.service.d.ts +2 -0
  111. package/dist/core/sdd/services/finalize.service.js +48 -2
  112. package/dist/core/sdd/services/historical-quality-regression.service.d.ts +35 -0
  113. package/dist/core/sdd/services/historical-quality-regression.service.js +228 -0
  114. package/dist/core/sdd/services/ingest-deposito.service.js +1 -1
  115. package/dist/core/sdd/services/planning-execution-coherence.service.d.ts +45 -0
  116. package/dist/core/sdd/services/planning-execution-coherence.service.js +225 -0
  117. package/dist/core/sdd/state.js +15 -5
  118. package/dist/core/sdd/types.d.ts +3 -3
  119. package/dist/core/sdd/workspace-schemas.d.ts +45 -4
  120. package/dist/core/sdd/workspace-schemas.js +27 -6
  121. package/dist/core/shared/skill-generation.d.ts +2 -0
  122. package/dist/core/shared/skill-generation.js +19 -2
  123. package/dist/core/shared/tool-detection.d.ts +19 -0
  124. package/dist/core/shared/tool-detection.js +89 -0
  125. package/package.json +6 -5
  126. package/schemas/sdd/5-quality.schema.json +43 -0
  127. package/schemas/sdd/reversa-evidence-bundle.schema.json +466 -0
  128. package/schemas/sdd/workspace-catalog.schema.json +511 -0
@@ -1,6 +1,10 @@
1
1
  import { buildPluginRuntimeInvocationPlan, pluginArtifactManifestSchema, } from './plugin-broker.js';
2
2
  import { pluginManifestSchema } from './plugin-manifest.js';
3
3
  import { createPluginRegistryState } from './plugin-registry.js';
4
+ import { DEFAULT_CODESDD_API_PROFILE_ID, resolveCodeSddApiProfile, } from './api-profile-catalog.js';
5
+ import { CODESDD_API_FOUNDATION_SHARED_BASELINE, CODESDD_API_SHARED_BASELINE_QUALITY_GATES, CODESDD_API_SHARED_BASELINE_REQUIREMENTS, getCodeSddApiSharedBaselineRequirements, } from './api-foundation-baseline.js';
6
+ import { CODESDD_FULL_FOUNDATION_COMPATIBLE_PROFILE_ID, CODESDD_FULL_FOUNDATION_PARITY_DIMENSIONS, CODESDD_FULL_FOUNDATION_PARITY_MATRIX, CODESDD_FULL_FOUNDATION_PARITY_QUALITY_GATES, getCodeSddFullFoundationParityMatrix, } from './api-foundation-parity.js';
7
+ import { buildCodeSddApiProfileDryRunProjection, getCodeSddApiProfileDryRunExpectation, } from './api-profile-dry-run-projection.js';
4
8
  export const DEVTRACK_API_APPLIANCE_PLUGIN_ID = 'codesdd-plugin-devtrack-api';
5
9
  export const DEVTRACK_API_APPLIANCE_CAPABILITIES = [
6
10
  'scaffold.project',
@@ -17,10 +21,12 @@ const DEVTRACK_API_SCAFFOLD_WRITE_SCOPE = [
17
21
  'src',
18
22
  'tests',
19
23
  'docs',
24
+ '.env.example',
20
25
  'package.json',
21
26
  'tsconfig.json',
22
27
  'nest-cli.json',
23
28
  'eslint.config.mjs',
29
+ '.sdd/plugin-evidence',
24
30
  ];
25
31
  export function evaluateDevTrackApiApplianceConformance(manifest) {
26
32
  const parsed = pluginManifestSchema.parse(manifest);
@@ -52,6 +58,9 @@ export function buildDevTrackApiScaffoldDryRunPlan(manifest, input) {
52
58
  const parsed = pluginManifestSchema.parse(manifest);
53
59
  const createdAt = input.created_at ?? new Date().toISOString();
54
60
  const packageName = normalizePackageName(input.package_name ?? input.project_name);
61
+ const apiProfile = resolveCodeSddApiProfile(input.api_profile, {
62
+ defaultProfile: DEFAULT_CODESDD_API_PROFILE_ID,
63
+ });
55
64
  const conformance = evaluateDevTrackApiApplianceConformance(parsed);
56
65
  if (!conformance.valid) {
57
66
  return {
@@ -64,8 +73,8 @@ export function buildDevTrackApiScaffoldDryRunPlan(manifest, input) {
64
73
  issues: conformance.issues,
65
74
  };
66
75
  }
67
- const artifacts = buildScaffoldArtifacts();
68
- const runtimePlan = buildRuntimePlan(parsed, input, packageName, createdAt, artifacts);
76
+ const artifacts = buildScaffoldArtifacts(apiProfile.profile_id);
77
+ const runtimePlan = buildRuntimePlan(parsed, input, packageName, createdAt, artifacts, apiProfile);
69
78
  if (runtimePlan.status !== 'ready' || !runtimePlan.envelope) {
70
79
  return {
71
80
  schema_version: 1,
@@ -89,6 +98,7 @@ export function buildDevTrackApiScaffoldDryRunPlan(manifest, input) {
89
98
  status: 'planned',
90
99
  created_at: createdAt,
91
100
  operation_id: operationId,
101
+ api_profile: apiProfile,
92
102
  project_name: input.project_name,
93
103
  package_name: packageName,
94
104
  runtime_plan: runtimePlan,
@@ -129,6 +139,9 @@ export function buildDevTrackApiScaffoldDryRunPlan(manifest, input) {
129
139
  projectName: input.project_name,
130
140
  packageName,
131
141
  validationCommands: parsed.validation.commands,
142
+ apiProfile,
143
+ expectedWriteScope: runtimePlan.envelope.write_scope,
144
+ artifacts,
132
145
  }),
133
146
  issues: [],
134
147
  };
@@ -146,7 +159,7 @@ function collectIdentityIssues(manifest) {
146
159
  }
147
160
  return issues;
148
161
  }
149
- function buildRuntimePlan(manifest, input, packageName, createdAt, artifacts) {
162
+ function buildRuntimePlan(manifest, input, packageName, createdAt, artifacts, apiProfile) {
150
163
  const registry = createPluginRegistryState([
151
164
  {
152
165
  manifest,
@@ -161,10 +174,12 @@ function buildRuntimePlan(manifest, input, packageName, createdAt, artifacts) {
161
174
  return buildPluginRuntimeInvocationPlan(registry, {
162
175
  feature_ref: input.feature_ref,
163
176
  capability: DEVTRACK_API_SCAFFOLD_CAPABILITY,
164
- skill_ref: 'devtrack-api',
177
+ skill_ref: apiProfile.profile_id,
165
178
  inputs: {
166
179
  project_name: input.project_name,
167
180
  package_name: packageName,
181
+ api_profile: apiProfile.profile_id,
182
+ api_profile_family: apiProfile.family_id,
168
183
  persistence: {
169
184
  provider: 'typeorm',
170
185
  },
@@ -187,6 +202,35 @@ function buildRuntimePlan(manifest, input, packageName, createdAt, artifacts) {
187
202
  });
188
203
  }
189
204
  function buildEvidenceManifest(input) {
205
+ const sharedBaselineRequirements = getCodeSddApiSharedBaselineRequirements();
206
+ const fullFoundationCompatibility = input.apiProfile.profile_id === CODESDD_FULL_FOUNDATION_COMPATIBLE_PROFILE_ID
207
+ ? {
208
+ id: CODESDD_FULL_FOUNDATION_PARITY_MATRIX.id,
209
+ version: CODESDD_FULL_FOUNDATION_PARITY_MATRIX.version,
210
+ profile_id: CODESDD_FULL_FOUNDATION_COMPATIBLE_PROFILE_ID,
211
+ source: CODESDD_FULL_FOUNDATION_PARITY_MATRIX.foundation_reference,
212
+ dimension_ids: CODESDD_FULL_FOUNDATION_PARITY_DIMENSIONS,
213
+ quality_gates: CODESDD_FULL_FOUNDATION_PARITY_QUALITY_GATES,
214
+ dimensions: getCodeSddFullFoundationParityMatrix().map((dimension) => ({
215
+ ...dimension,
216
+ status: 'pending',
217
+ })),
218
+ }
219
+ : undefined;
220
+ const profileProjection = buildCodeSddApiProfileDryRunProjection({
221
+ apiProfile: input.apiProfile,
222
+ expectedWriteScope: input.expectedWriteScope,
223
+ artifactMapRefs: input.artifacts.map((artifactEntry) => ({
224
+ path: artifactEntry.path,
225
+ layer: artifactEntry.layer,
226
+ artifact_kind: artifactEntry.artifact_kind,
227
+ role: artifactEntry.role,
228
+ content_type: artifactEntry.content_type,
229
+ source_reference: artifactEntry.source_reference,
230
+ tags: artifactEntry.tags,
231
+ })),
232
+ validationCommands: input.validationCommands,
233
+ });
190
234
  return {
191
235
  schema_version: 1,
192
236
  operation_id: input.operationId,
@@ -207,43 +251,100 @@ function buildEvidenceManifest(input) {
207
251
  command,
208
252
  status: 'pending',
209
253
  })),
210
- quality_gates: [
211
- 'typeorm-only-persistence',
254
+ quality_gates: unique([
255
+ ...profileProjection.expected_quality_gates,
212
256
  'no-secret-fixtures',
213
257
  'no-out-of-root-writes',
214
258
  'artifact-manifest-required',
215
259
  'evidence-manifest-required',
216
- ],
260
+ ]),
261
+ api_profile: {
262
+ family_id: input.apiProfile.family_id,
263
+ selected_profile: input.apiProfile.profile_id,
264
+ requested_profile: input.apiProfile.input,
265
+ legacy_alias: input.apiProfile.legacy_alias,
266
+ migration_notice: input.apiProfile.migration_notice,
267
+ inherited_baseline: CODESDD_API_SHARED_BASELINE_REQUIREMENTS,
268
+ },
269
+ profile_projection: profileProjection,
270
+ foundation_baseline: {
271
+ id: CODESDD_API_FOUNDATION_SHARED_BASELINE.id,
272
+ version: CODESDD_API_FOUNDATION_SHARED_BASELINE.version,
273
+ source: CODESDD_API_FOUNDATION_SHARED_BASELINE.foundation_reference,
274
+ requirement_ids: CODESDD_API_SHARED_BASELINE_REQUIREMENTS,
275
+ quality_gates: CODESDD_API_SHARED_BASELINE_QUALITY_GATES,
276
+ requirements: sharedBaselineRequirements,
277
+ },
278
+ ...(fullFoundationCompatibility
279
+ ? {
280
+ full_foundation_compatibility: fullFoundationCompatibility,
281
+ }
282
+ : {}),
217
283
  };
218
284
  }
219
- function buildScaffoldArtifacts() {
220
- return [
221
- artifact('package.json', 'root', 'package-metadata', 'manifest', 'application/json', 'Foundation-compatible package metadata, scripts, and dependencies.'),
222
- artifact('tsconfig.json', 'config', 'configuration', 'manifest', 'application/json', 'TypeScript path aliases and compiler settings aligned to Foundation API.'),
223
- artifact('nest-cli.json', 'config', 'configuration', 'manifest', 'application/json', 'Nest CLI configuration with Swagger plugin support.'),
224
- artifact('eslint.config.mjs', 'config', 'configuration', 'policy', 'text/javascript', 'Foundation-compatible lint rules and import-boundary checks.'),
225
- artifact('docs/foundation-backend-reference-structure.md', 'docs', 'documentation', 'documentation', 'text/markdown', 'Derived Foundation package structure reference for maintainers.'),
226
- artifact('src/main.ts', 'root', 'source', 'implementation', 'text/typescript', 'NestJS bootstrap entrypoint.'),
227
- artifact('src/app.module.ts', 'root', 'source', 'module', 'text/typescript', 'Root module composing application, infrastructure, and presentation layers.'),
228
- artifact('src/application/application.module.ts', 'application', 'source', 'module', 'text/typescript', 'Application layer module boundary.'),
229
- artifact('src/application/runtime-settings.ts', 'application', 'source', 'type', 'text/typescript', 'Application runtime settings boundary.'),
230
- artifact('src/domain/auth/business-objects/api-keys.bo.ts', 'domain', 'source', 'business-object', 'text/typescript', 'Initial BO-pattern domain object example from Foundation API.'),
231
- artifact('src/application/business/auth/ports/out/api-key-repository.port.ts', 'application', 'source', 'repository-port', 'text/typescript', 'BO-pattern repository port owned by application ports/out.'),
232
- artifact('src/infrastructure/infrastructure.module.ts', 'infrastructure', 'source', 'module', 'text/typescript', 'Infrastructure layer module boundary.'),
233
- artifact('src/infrastructure/settings/app-configuration.ts', 'infrastructure', 'source', 'implementation', 'text/typescript', 'Typed application configuration source.'),
234
- artifact('src/infrastructure/adapters/orm/entities/api-key.orm-entity.ts', 'infrastructure', 'source', 'entity', 'text/typescript', 'TypeORM persistence entity kept in the centralized orm subsystem.'),
235
- artifact('src/presentation/presentation.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'Presentation layer module boundary.'),
236
- artifact('src/presentation/rest/rest.presentation.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'REST channel module boundary.'),
237
- artifact('src/presentation/graphql/graphql.presentation.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'GraphQL channel module boundary.'),
238
- artifact('src/presentation/cli/cli.presentation.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'CLI channel module boundary.'),
239
- artifact('src/presentation/websocket/websocket.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'WebSocket channel module boundary.'),
240
- artifact('src/shared/domain/generic-business-object.ts', 'shared', 'source', 'abstraction', 'text/typescript', 'Shared domain primitive used by Foundation packages.'),
241
- artifact('src/shared/presentation/generic-controller.ts', 'shared', 'source', 'abstraction', 'text/typescript', 'Shared presentation primitive used by REST controllers.'),
242
- artifact('tests/app.e2e-spec.ts', 'tests', 'test', 'test', 'text/typescript', 'Initial E2E smoke test for the generated API scaffold.'),
243
- artifact('tests/jest-e2e.json', 'tests', 'configuration', 'manifest', 'application/json', 'Jest E2E configuration for the scaffold.'),
285
+ function buildScaffoldArtifacts(apiProfile) {
286
+ const baselineArtifacts = [
287
+ artifact('package.json', 'root', 'package-metadata', 'manifest', 'application/json', 'Foundation-compatible package metadata, scripts, and dependencies.', apiProfile),
288
+ artifact('.env.example', 'config', 'configuration', 'manifest', 'text/plain', 'Safe placeholder environment contract, including app, database, JWT, and Swagger server variables.', apiProfile),
289
+ artifact('tsconfig.json', 'config', 'configuration', 'manifest', 'application/json', 'TypeScript path aliases and compiler settings aligned to Foundation API.', apiProfile),
290
+ artifact('nest-cli.json', 'config', 'configuration', 'manifest', 'application/json', 'Nest CLI configuration with Swagger plugin support.', apiProfile),
291
+ artifact('eslint.config.mjs', 'config', 'configuration', 'policy', 'text/javascript', 'Foundation-compatible lint rules and import-boundary checks.', apiProfile),
292
+ artifact('docs/foundation-backend-reference-structure.md', 'docs', 'documentation', 'documentation', 'text/markdown', 'Derived Foundation package structure reference for maintainers.', apiProfile),
293
+ artifact('src/main.ts', 'root', 'source', 'implementation', 'text/typescript', 'NestJS bootstrap entrypoint with validation pipe and Swagger/OpenAPI /docs setup.', apiProfile),
294
+ artifact('src/app.module.ts', 'root', 'source', 'module', 'text/typescript', 'Root module composing application, infrastructure, and presentation layers.', apiProfile),
295
+ artifact('src/application/application.module.ts', 'application', 'source', 'module', 'text/typescript', 'Application layer module boundary.', apiProfile),
296
+ artifact('src/application/runtime-settings.ts', 'application', 'source', 'type', 'text/typescript', 'Application runtime settings boundary.', apiProfile),
297
+ artifact('src/domain/auth/business-objects/api-keys.bo.ts', 'domain', 'source', 'business-object', 'text/typescript', 'Initial BO-pattern domain object example from Foundation API.', apiProfile),
298
+ artifact('src/application/business/auth/ports/out/api-key-repository.port.ts', 'application', 'source', 'repository-port', 'text/typescript', 'BO-pattern repository port owned by application ports/out.', apiProfile),
299
+ artifact('src/application/business/auth/ports/in/register.use-case.port.ts', 'application', 'source', 'interface', 'text/typescript', 'Application input port for a user-facing auth route.', apiProfile),
300
+ artifact('src/application/business/auth/use-cases/register.use-case.ts', 'application', 'source', 'use-case', 'text/typescript', 'Application use case backing a user-facing route before presentation wiring.', apiProfile),
301
+ artifact('src/application/business/auth/auth.application.module.ts', 'application', 'source', 'module', 'text/typescript', 'Application auth module wiring input ports, use cases, services, and output ports.', apiProfile),
302
+ artifact('src/infrastructure/infrastructure.module.ts', 'infrastructure', 'source', 'module', 'text/typescript', 'Infrastructure layer module boundary.', apiProfile),
303
+ artifact('src/infrastructure/settings/app-configuration.ts', 'infrastructure', 'source', 'implementation', 'text/typescript', 'Typed application configuration source.', apiProfile),
304
+ artifact('src/infrastructure/adapters/orm/entities/api-key.orm-entity.ts', 'infrastructure', 'source', 'entity', 'text/typescript', 'TypeORM persistence entity kept in the centralized orm subsystem.', apiProfile),
305
+ artifact('src/presentation/presentation.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'Presentation layer module boundary.', apiProfile),
306
+ artifact('src/presentation/rest/rest.presentation.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'REST channel module boundary.', apiProfile),
307
+ artifact('src/presentation/rest/auth/auth.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'REST auth module registering controllers, guards, and decorators.', apiProfile),
308
+ artifact('src/presentation/rest/auth/controllers/register.controller.ts', 'presentation', 'source', 'controller', 'text/typescript', 'Swagger-documented REST controller that injects an application input port.', apiProfile),
309
+ artifact('src/presentation/rest/auth/dtos/register-input.dto.ts', 'presentation', 'source', 'dto', 'text/typescript', 'Swagger-documented REST input DTO for a user-facing route.', apiProfile),
310
+ artifact('src/presentation/rest/auth/dtos/auth-session-output.dto.ts', 'presentation', 'source', 'dto', 'text/typescript', 'Swagger-documented REST output DTO for session responses.', apiProfile),
311
+ artifact('src/presentation/rest/auth/guards/jwt-auth.guard.ts', 'presentation', 'source', 'implementation', 'text/typescript', 'REST route guard baseline for protected bearer routes.', apiProfile),
312
+ artifact('src/presentation/rest/auth/guards/permission.guard.ts', 'presentation', 'source', 'implementation', 'text/typescript', 'REST authorization guard baseline for permission-protected routes.', apiProfile),
313
+ artifact('src/presentation/rest/auth/decorators/permission.decorator.ts', 'presentation', 'source', 'policy', 'text/typescript', 'REST authorization decorator baseline for permission metadata.', apiProfile),
314
+ artifact('src/presentation/dtos/api-error-response.dto.ts', 'presentation', 'source', 'dto', 'text/typescript', 'Swagger-documented error response DTO for controller response metadata.', apiProfile),
315
+ artifact('src/presentation/graphql/graphql.presentation.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'GraphQL channel module boundary.', apiProfile),
316
+ artifact('src/presentation/cli/cli.presentation.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'CLI channel module boundary.', apiProfile),
317
+ artifact('src/presentation/websocket/websocket.module.ts', 'presentation', 'source', 'module', 'text/typescript', 'WebSocket channel module boundary.', apiProfile),
318
+ artifact('src/shared/domain/generic-business-object.ts', 'shared', 'source', 'abstraction', 'text/typescript', 'Shared domain primitive used by Foundation packages.', apiProfile),
319
+ artifact('src/shared/presentation/generic-controller.ts', 'shared', 'source', 'abstraction', 'text/typescript', 'Shared presentation primitive used by REST controllers.', apiProfile),
320
+ artifact('tests/app.e2e-spec.ts', 'tests', 'test', 'test', 'text/typescript', 'Initial E2E smoke test for the generated API scaffold.', apiProfile),
321
+ artifact('tests/jest-e2e.json', 'tests', 'configuration', 'manifest', 'application/json', 'Jest E2E configuration for the scaffold.', apiProfile),
244
322
  ];
323
+ const plannedPaths = new Set(baselineArtifacts.map((entry) => entry.path));
324
+ const profileOverlayArtifacts = getCodeSddApiProfileDryRunExpectation(apiProfile).expected_writes
325
+ .filter((expectedWrite) => !plannedPaths.has(expectedWrite.path))
326
+ .map((expectedWrite) => artifact(expectedWrite.path, expectedWrite.layer, expectedWrite.artifact_kind, expectedWrite.role, contentTypeForScaffoldPath(expectedWrite.path, expectedWrite.artifact_kind), `${expectedWrite.reason} (Profile overlay for ${apiProfile}.)`, apiProfile));
327
+ return [...baselineArtifacts, ...profileOverlayArtifacts];
245
328
  }
246
- function artifact(artifactPath, layer, artifactKind, role, contentType, reason) {
329
+ function contentTypeForScaffoldPath(artifactPath, artifactKind) {
330
+ if (artifactPath.endsWith('.ts')) {
331
+ return 'text/typescript';
332
+ }
333
+ if (artifactPath.endsWith('.json')) {
334
+ return 'application/json';
335
+ }
336
+ if (artifactPath.endsWith('.md')) {
337
+ return 'text/markdown';
338
+ }
339
+ if (artifactPath.endsWith('.yaml') || artifactPath.endsWith('.yml')) {
340
+ return 'text/yaml';
341
+ }
342
+ if (artifactKind === 'documentation') {
343
+ return 'text/markdown';
344
+ }
345
+ return 'text/plain';
346
+ }
347
+ function artifact(artifactPath, layer, artifactKind, role, contentType, reason, apiProfile) {
247
348
  const mapEntry = {
248
349
  path: artifactPath,
249
350
  layer,
@@ -256,7 +357,7 @@ function artifact(artifactPath, layer, artifactKind, role, contentType, reason)
256
357
  implementation: role === 'interface' || role === 'repository-port' ? 'contract' : 'generated',
257
358
  decision_refs: ['EPIC-0075'],
258
359
  source_refs: [`${DEVTRACK_API_REFERENCE_ROOT}/${artifactPath}`],
259
- tags: ['devtrack-api', 'foundation-api'],
360
+ tags: ['devtrack-api', 'foundation-api', 'codesdd-api-profile', apiProfile],
260
361
  metadata: {},
261
362
  };
262
363
  return {
@@ -277,4 +378,7 @@ function normalizePackageName(value) {
277
378
  }
278
379
  return normalized;
279
380
  }
381
+ function unique(values) {
382
+ return [...new Set(values)];
383
+ }
280
384
  //# sourceMappingURL=devtrack-api-appliance.js.map
@@ -24,6 +24,22 @@ export interface DevTrackApiArchitectureValidationResult {
24
24
  architecture_schema: QualityArchitectureSchema;
25
25
  import_graph: QualityImportGraph;
26
26
  findings: DevTrackApiArchitectureFinding[];
27
+ drift_signals: DevTrackApiDriftSignal[];
28
+ profile_outcomes: DevTrackApiProfileOutcome[];
29
+ }
30
+ export type DevTrackApiDriftClass = 'CVD-01' | 'CVD-02' | 'CVD-03' | 'CVD-04' | 'CVD-05' | 'CVD-06' | 'CVD-07' | 'CVD-08' | 'CVD-09' | 'WCA-01' | 'WCA-02' | 'WCA-03';
31
+ export interface DevTrackApiDriftSignal {
32
+ drift_class: DevTrackApiDriftClass;
33
+ observed: string;
34
+ mapped_rules: string[];
35
+ finding_codes: DevTrackApiArchitectureIssueCode[];
36
+ }
37
+ export interface DevTrackApiProfileOutcome {
38
+ profile: 'prototype' | 'foundation-compatible' | 'enterprise-strict';
39
+ status: 'passed' | 'warning' | 'blocked';
40
+ blocking_rules: string[];
41
+ blocking_drift_classes: DevTrackApiDriftClass[];
42
+ exception_candidate_rules: string[];
27
43
  }
28
44
  export declare function buildDevTrackApiArchitectureSchema(): QualityArchitectureSchema;
29
45
  export declare function collectDevTrackApiImportGraph(input: CollectDevTrackApiImportGraphInput): Promise<QualityImportGraph>;
@@ -1,6 +1,8 @@
1
1
  import { promises as fs } from 'node:fs';
2
2
  import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
3
4
  import ts from 'typescript';
5
+ import { parse as parseYaml } from 'yaml';
4
6
  import { parseQualityArchitectureSchema, } from './quality-validation.js';
5
7
  export const DEVTRACK_API_ARCHITECTURE_SCHEMA_ID = 'ARCH-GATE-devtrack-api-p0';
6
8
  const DEFAULT_SOURCE_ROOTS = ['src', 'prisma'];
@@ -17,6 +19,30 @@ const DEVTRACK_ALIAS_PREFIXES = [
17
19
  '@shared/',
18
20
  '@src/',
19
21
  ];
22
+ const DEVTRACK_API_CONTRACT_PACK_PATH = fileURLToPath(new URL('../../../.sdd/skills/curated/devtrack-api/references/contract-pack.yaml', import.meta.url));
23
+ const DRIFT_CLASS_TO_FINDING_CODES = {
24
+ 'CVD-02': [
25
+ 'ARCH_RELATIVE_IMPORT_FORBIDDEN',
26
+ 'ARCH_APPLICATION_PRESENTATION_IMPORT',
27
+ 'ARCH_APPLICATION_CONCRETE_INFRA_IMPORT',
28
+ 'ARCH_PRESENTATION_INFRA_IMPORT',
29
+ 'ARCH_TYPEORM_IMPORT_OUTSIDE_INFRASTRUCTURE',
30
+ 'ARCH_TYPEORM_ENTITY_PATH_INVALID',
31
+ 'ARCH_TYPEORM_ENTITY_SUFFIX_INVALID',
32
+ 'ARCH_TYPEORM_REPOSITORY_PATH_INVALID',
33
+ 'ARCH_TYPEORM_REPOSITORY_SUFFIX_INVALID',
34
+ 'ARCH_PRESENTATION_TRANSPORT_MISSING',
35
+ 'ARCH_INFRASTRUCTURE_CONTEXT_PERSISTENCE_FORBIDDEN',
36
+ ],
37
+ 'CVD-03': ['ARCH_TYPEORM_REPOSITORY_FAKE'],
38
+ 'CVD-04': ['ARCH_PRESENTATION_COMPOSITION_ROOT', 'ARCH_AGGREGATE_MODULE_MISSING', 'ARCH_AGGREGATE_MODULE_NOT_NESTJS'],
39
+ 'CVD-05': ['ARCH_PORT_MISSING_SYMBOL', 'ARCH_PORT_GROUPED_UNRELATED'],
40
+ 'CVD-06': ['ARCH_BO_MISSING_METHODS', 'ARCH_VO_MISSING_METHODS'],
41
+ 'CVD-07': ['ARCH_MISSING_DATASOURCE', 'ARCH_MISSING_MIGRATIONS', 'ARCH_MISSING_TYPEORM_MODULE_FORFEATURE'],
42
+ 'CVD-09': ['ARCH_DOMAIN_REPOSITORY_PORT_CONTEXT_FORBIDDEN'],
43
+ 'WCA-02': ['ARCH_RELATIVE_IMPORT_FORBIDDEN'],
44
+ 'WCA-03': ['ARCH_TYPEORM_REPOSITORY_FAKE', 'ARCH_MISSING_TYPEORM_MODULE_FORFEATURE'],
45
+ };
20
46
  export function buildDevTrackApiArchitectureSchema() {
21
47
  return parseQualityArchitectureSchema({
22
48
  schema_version: 1,
@@ -157,13 +183,73 @@ export async function validateDevTrackApiArchitecture(input) {
157
183
  detectMissingAggregateModules(files, fileContents, findings);
158
184
  detectMissingRuntimePersistence(files, fileContents, findings);
159
185
  const dedupedFindings = dedupeFindings(findings);
186
+ const contractPack = await loadDevTrackApiContractPack();
187
+ const driftSignals = mapFindingsToDriftSignals(dedupedFindings, contractPack);
188
+ const profileOutcomes = buildProfileOutcomes(driftSignals, contractPack);
160
189
  return {
161
190
  status: dedupedFindings.length > 0 ? 'warning' : 'passed',
162
191
  architecture_schema: buildDevTrackApiArchitectureSchema(),
163
192
  import_graph: importGraph,
164
193
  findings: dedupedFindings,
194
+ drift_signals: driftSignals,
195
+ profile_outcomes: profileOutcomes,
165
196
  };
166
197
  }
198
+ async function loadDevTrackApiContractPack() {
199
+ const raw = await fs.readFile(DEVTRACK_API_CONTRACT_PACK_PATH, 'utf-8');
200
+ return parseYaml(raw);
201
+ }
202
+ function mapFindingsToDriftSignals(findings, contractPack) {
203
+ const findingCodes = new Set(findings.map((finding) => finding.code));
204
+ const driftSignals = [];
205
+ for (const [driftClass, mappedFindingCodes] of Object.entries(DRIFT_CLASS_TO_FINDING_CODES)) {
206
+ const matchedCodes = mappedFindingCodes.filter((code) => findingCodes.has(code));
207
+ if (matchedCodes.length === 0)
208
+ continue;
209
+ const mapping = contractPack.codesdd_validate_drift_map[driftClass] ?? contractPack.field_evidence_drift_map[driftClass];
210
+ driftSignals.push({
211
+ drift_class: driftClass,
212
+ observed: mapping?.observed ?? 'Observed semantic drift mapped from validator findings.',
213
+ mapped_rules: [...new Set(mapping?.mapped_rules ?? [])],
214
+ finding_codes: matchedCodes,
215
+ });
216
+ }
217
+ return driftSignals.sort((left, right) => left.drift_class.localeCompare(right.drift_class));
218
+ }
219
+ function buildProfileOutcomes(driftSignals, contractPack) {
220
+ const ruleSeverity = new Map(contractPack.rules.map((rule) => [rule.id, rule.severity]));
221
+ const ruleIds = [...new Set(driftSignals.flatMap((signal) => signal.mapped_rules))];
222
+ const p0Rules = ruleIds.filter((ruleId) => ruleSeverity.get(ruleId) === 'P0');
223
+ const p1Rules = ruleIds.filter((ruleId) => ruleSeverity.get(ruleId) === 'P1');
224
+ const p2Rules = ruleIds.filter((ruleId) => ruleSeverity.get(ruleId) === 'P2');
225
+ return [
226
+ {
227
+ profile: 'prototype',
228
+ status: driftSignals.length > 0 ? 'warning' : 'passed',
229
+ blocking_rules: [],
230
+ blocking_drift_classes: [],
231
+ exception_candidate_rules: [],
232
+ },
233
+ {
234
+ profile: 'foundation-compatible',
235
+ status: p0Rules.length > 0 ? 'blocked' : driftSignals.length > 0 ? 'warning' : 'passed',
236
+ blocking_rules: p0Rules,
237
+ blocking_drift_classes: driftSignals
238
+ .filter((signal) => signal.mapped_rules.some((ruleId) => p0Rules.includes(ruleId)))
239
+ .map((signal) => signal.drift_class),
240
+ exception_candidate_rules: [...new Set([...p1Rules, ...p2Rules])],
241
+ },
242
+ {
243
+ profile: 'enterprise-strict',
244
+ status: p0Rules.length > 0 || p1Rules.length > 0 ? 'blocked' : driftSignals.length > 0 ? 'warning' : 'passed',
245
+ blocking_rules: [...new Set([...p0Rules, ...p1Rules])],
246
+ blocking_drift_classes: driftSignals
247
+ .filter((signal) => signal.mapped_rules.some((ruleId) => p0Rules.includes(ruleId) || p1Rules.includes(ruleId)))
248
+ .map((signal) => signal.drift_class),
249
+ exception_candidate_rules: p2Rules,
250
+ },
251
+ ];
252
+ }
167
253
  function finding(code, filePath, importSpecifier, message, remediation) {
168
254
  return {
169
255
  code,
@@ -53,7 +53,7 @@ Initial operational directives:
53
53
  - CodeSDD is the official planner for any build request; other planners or agent-native plans are secondary execution aids only.
54
54
  - In initialized CodeSDD repositories, any user request that implies implementation, file edits, validation, execution, or finalize must be treated as requiring CodeSDD planning unless the user explicitly marks it as read-only or outside CodeSDD.
55
55
  - For change requests, agents must bind the work to an active or ready FEAT through \`${CLI_NAME} sdd next\` and \`${CLI_NAME} sdd context <FEAT-ID>\` before implementation; agent-native plans may only decompose execution after that CodeSDD context exists.
56
- - For API/backend work, use \`devtrack-api\` by default unless the user or SDD context explicitly selects another skill/profile; Python/Flask API work stays routed to \`api-clean-flask-langgraph\`.
56
+ - For API/backend work, select a CodeSDD API profile (\`minimal-rest\`, \`rest-auth-rbac\`, \`rest-crud-typeorm\`, \`evented-api\`, \`ai-agent-api\`, or \`full-foundation-compatible\`); \`devtrack-api\` remains the compatibility skill/alias and Python/Flask API work stays routed to \`api-clean-flask-langgraph\`.
57
57
  - During init, onboard, insight, and debate flows, CodeSDD-managed agent instruction blocks must be inspected and reconfigured when they drift from this contract.
58
58
  - Commit requests must follow Conventional Commits, selective staging, and grouping by modified directory plus change protocol (\`src\`, \`${memoryDir}\`, docs, config, infra, dependencies, or generated files).
59
59
 
@@ -116,7 +116,7 @@ Initial directives:
116
116
  - CodeSDD is the official planner for requested work; model-native plans and other planning tools are subordinate to CodeSDD artifacts.
117
117
  - In initialized CodeSDD repositories, implementation, edit, validation, execution, and finalize requests implicitly require CodeSDD planning unless the user explicitly marks the request as read-only or outside CodeSDD.
118
118
  - A change request must use the active or ready FEAT returned by \`${CLI_NAME} sdd next\` and must load \`${CLI_NAME} sdd context <FEAT-ID>\` before coding; model-native plans may only refine execution after that context exists.
119
- - API/backend work uses \`devtrack-api\` by default unless an explicit skill/profile says otherwise; Python/Flask API work uses \`api-clean-flask-langgraph\`.
119
+ - API/backend work selects a CodeSDD API profile (\`minimal-rest\`, \`rest-auth-rbac\`, \`rest-crud-typeorm\`, \`evented-api\`, \`ai-agent-api\`, or \`full-foundation-compatible\`); \`devtrack-api\` remains the compatibility skill/alias, and Python/Flask API work uses \`api-clean-flask-langgraph\`.
120
120
  - CodeSDD-managed blocks in \`AGENTS.md\`, \`AGENT.md\`, \`CLAUDE.md\`, \`GEMINI.md\`, \`.codex\`, \`.opencode\`, \`.ai\`, \`.cloud\`, or equivalent agent files must be inspected and normalized during init/onboard/insight/debate when CodeSDD owns project governance.
121
121
  - Commits must use Conventional Commits, selective staging, and grouping by modified directory plus protocol: source, \`${memoryDir}\`, docs, config, infra, dependencies, generated files, renames, or deletions.`;
122
122
  }
@@ -150,7 +150,7 @@ Initial directives:
150
150
  - CodeSDD is the official planner. Other planning systems may assist execution only after CodeSDD context exists.
151
151
  - In initialized CodeSDD repositories, implementation, edit, validation, execution, and finalize requests implicitly require CodeSDD planning unless the user explicitly marks the request as read-only or outside CodeSDD.
152
152
  - Agents must bind each change request to the active or ready FEAT returned by \`${CLI_NAME} sdd next\` and load \`${CLI_NAME} sdd context <FEAT-ID>\` before coding.
153
- - API/backend work defaults to \`devtrack-api\` unless an explicit skill/profile overrides it; Python/Flask API work remains a documented exception routed to \`api-clean-flask-langgraph\`.
153
+ - API/backend work selects a CodeSDD API profile (\`minimal-rest\`, \`rest-auth-rbac\`, \`rest-crud-typeorm\`, \`evented-api\`, \`ai-agent-api\`, or \`full-foundation-compatible\`); \`devtrack-api\` remains the compatibility skill/alias, and Python/Flask API work remains a documented exception routed to \`api-clean-flask-langgraph\`.
154
154
  - CodeSDD lifecycle entrypoints must inspect and normalize CodeSDD-managed agent instruction blocks in root and tool-specific agent files.
155
155
  - Commit work must use Conventional Commits, selective staging, and directory/protocol grouping. Source changes, \`${memoryDir}\` governance, docs, config, infra, dependencies, generated files, renames, and deletions should be staged and committed separately unless indivisible.`;
156
156
  }
@@ -0,0 +1,27 @@
1
+ import type { ArtifactAllocatorLease } from './artifact-id-allocator.js';
2
+ import type { EnterpriseProvisioningPolicyReport } from './enterprise-provisioning-policy.js';
3
+ export type EnterpriseCommandGateDecision = 'allow' | 'block' | 'bypass-detected';
4
+ export interface EnterpriseMutatingCommandGateRequest {
5
+ command: string;
6
+ mutates_numbered_artifacts: boolean;
7
+ provisioning: EnterpriseProvisioningPolicyReport;
8
+ project_id?: string;
9
+ tenant_id?: string;
10
+ artifact_type?: ArtifactAllocatorLease['artifact_type'];
11
+ lease?: ArtifactAllocatorLease;
12
+ fencing_token?: number;
13
+ now: string;
14
+ bypass_requested?: boolean;
15
+ bypass_reason?: string;
16
+ }
17
+ export interface EnterpriseMutatingCommandGateResult {
18
+ decision: EnterpriseCommandGateDecision;
19
+ reason: string;
20
+ required: boolean;
21
+ bypass_detected: boolean;
22
+ requested_mode: 'local' | 'enterprise';
23
+ effective_mode: 'local' | 'enterprise';
24
+ local_mode_exception_accepted: boolean;
25
+ }
26
+ export declare function evaluateEnterpriseMutatingCommandGate(request: EnterpriseMutatingCommandGateRequest): EnterpriseMutatingCommandGateResult;
27
+ //# sourceMappingURL=enterprise-mutating-command-gate.d.ts.map
@@ -0,0 +1,104 @@
1
+ import { validateAllocatorFencingToken } from './artifact-id-allocator.js';
2
+ export function evaluateEnterpriseMutatingCommandGate(request) {
3
+ const requestedMode = request.provisioning.requested_mode ?? request.provisioning.mode;
4
+ const effectiveMode = request.provisioning.effective_mode ??
5
+ (request.provisioning.requested && request.provisioning.status !== 'disabled' ? 'enterprise' : 'local');
6
+ const localModeExceptionAccepted = request.provisioning.local_mode_exception_accepted ??
7
+ (!request.provisioning.requested || request.provisioning.status === 'disabled');
8
+ if (!request.mutates_numbered_artifacts) {
9
+ return {
10
+ decision: 'allow',
11
+ reason: `Command ${request.command} does not mutate numbered artifacts.`,
12
+ required: false,
13
+ bypass_detected: false,
14
+ requested_mode: requestedMode,
15
+ effective_mode: effectiveMode,
16
+ local_mode_exception_accepted: localModeExceptionAccepted,
17
+ };
18
+ }
19
+ if (request.bypass_requested) {
20
+ return {
21
+ decision: 'bypass-detected',
22
+ reason: request.bypass_reason
23
+ ? `Bypass requested for ${request.command}: ${request.bypass_reason}`
24
+ : `Bypass requested for ${request.command} without an auditable reason.`,
25
+ required: true,
26
+ bypass_detected: true,
27
+ requested_mode: requestedMode,
28
+ effective_mode: effectiveMode,
29
+ local_mode_exception_accepted: localModeExceptionAccepted,
30
+ };
31
+ }
32
+ if (!request.provisioning.requested || request.provisioning.status === 'disabled') {
33
+ return {
34
+ decision: 'allow',
35
+ reason: 'Enterprise provisioning is not requested for this mutation; local mode exception is accepted and numbered artifact mutation is allowed.',
36
+ required: false,
37
+ bypass_detected: false,
38
+ requested_mode: requestedMode,
39
+ effective_mode: 'local',
40
+ local_mode_exception_accepted: true,
41
+ };
42
+ }
43
+ if (request.provisioning.status !== 'ready') {
44
+ return {
45
+ decision: 'block',
46
+ reason: `Enterprise provisioning is ${request.provisioning.status} with requested_mode=${requestedMode} and effective_mode=enterprise: ` +
47
+ request.provisioning.reason,
48
+ required: true,
49
+ bypass_detected: false,
50
+ requested_mode: requestedMode,
51
+ effective_mode: 'enterprise',
52
+ local_mode_exception_accepted: false,
53
+ };
54
+ }
55
+ if (!request.lease || request.fencing_token === undefined) {
56
+ return {
57
+ decision: 'block',
58
+ reason: `Command ${request.command} requires an active allocator lease and fencing token in Enterprise mode.`,
59
+ required: true,
60
+ bypass_detected: false,
61
+ requested_mode: requestedMode,
62
+ effective_mode: 'enterprise',
63
+ local_mode_exception_accepted: false,
64
+ };
65
+ }
66
+ if ((request.project_id !== undefined && request.lease.project_id !== request.project_id) ||
67
+ (request.tenant_id !== undefined && request.lease.tenant_id !== request.tenant_id) ||
68
+ (request.artifact_type !== undefined && request.lease.artifact_type !== request.artifact_type)) {
69
+ return {
70
+ decision: 'block',
71
+ reason: `Command ${request.command} allocator lease scope does not match the requested mutation scope.`,
72
+ required: true,
73
+ bypass_detected: false,
74
+ requested_mode: requestedMode,
75
+ effective_mode: 'enterprise',
76
+ local_mode_exception_accepted: false,
77
+ };
78
+ }
79
+ const fencing = validateAllocatorFencingToken(request.lease, {
80
+ fencing_token: request.fencing_token,
81
+ now: request.now,
82
+ });
83
+ if (!fencing.valid) {
84
+ return {
85
+ decision: 'block',
86
+ reason: `Command ${request.command} allocator fencing token is ${fencing.reason}.`,
87
+ required: true,
88
+ bypass_detected: false,
89
+ requested_mode: requestedMode,
90
+ effective_mode: 'enterprise',
91
+ local_mode_exception_accepted: false,
92
+ };
93
+ }
94
+ return {
95
+ decision: 'allow',
96
+ reason: `Command ${request.command} has a valid Enterprise allocator lease and fencing token.`,
97
+ required: true,
98
+ bypass_detected: false,
99
+ requested_mode: requestedMode,
100
+ effective_mode: 'enterprise',
101
+ local_mode_exception_accepted: false,
102
+ };
103
+ }
104
+ //# sourceMappingURL=enterprise-mutating-command-gate.js.map
@@ -0,0 +1,20 @@
1
+ import type { ArtifactIdAllocatorState } from './artifact-id-allocator.js';
2
+ export interface EnterpriseProvenanceFinding {
3
+ severity: 'blocker' | 'warning';
4
+ code: string;
5
+ message: string;
6
+ ref?: string;
7
+ }
8
+ export interface EnterpriseProvenanceReport {
9
+ valid: boolean;
10
+ findings: EnterpriseProvenanceFinding[];
11
+ counters: {
12
+ reservations: number;
13
+ leases: number;
14
+ canonical_writes: number;
15
+ drafts: number;
16
+ audit_events: number;
17
+ };
18
+ }
19
+ export declare function evaluateEnterpriseAllocatorProvenance(state: ArtifactIdAllocatorState): EnterpriseProvenanceReport;
20
+ //# sourceMappingURL=enterprise-provenance-gates.d.ts.map