phasegate 0.229.0 → 0.264.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/CHANGELOG.md +73 -1
  2. package/README.ja.md +31 -1
  3. package/README.md +30 -0
  4. package/docs/ADR/031-world-model-ownership-and-corpus-lifecycle.md +155 -0
  5. package/docs/ADR/032-world-node-identity.md +198 -0
  6. package/docs/ADR/033-world-snapshot-canonicalization.md +246 -0
  7. package/docs/ADR/034-world-constraint-semantics.md +218 -0
  8. package/docs/ADR/035-world-adoption-baseline-and-waiver.md +341 -0
  9. package/docs/ADR/036-world-model-and-doc-freshness.md +169 -0
  10. package/docs/ADR/037-world-cli-and-output-contract.md +398 -0
  11. package/docs/contracts/attestation-v2.schema.json +110 -0
  12. package/docs/contracts/requirement-test-matrix.schema.json +15 -0
  13. package/docs/contracts/world-baseline.schema.json +35 -0
  14. package/docs/contracts/world-constraints.schema.json +56 -0
  15. package/docs/contracts/world-debts.schema.json +32 -0
  16. package/docs/contracts/world-obligation-report.schema.json +259 -0
  17. package/docs/contracts/world-waivers.schema.json +32 -0
  18. package/docs/guide/cli-reference.md +45 -0
  19. package/docs/guide/configuration.md +56 -0
  20. package/docs/templates/ci/aidlc-gate.yml +42 -2
  21. package/package.json +1 -1
  22. package/scripts/harness/agent-integration/application/dto/open-world-obligations-context-dto.ts +30 -0
  23. package/scripts/harness/agent-integration/application/ports/world-obligations-query-port.ts +30 -0
  24. package/scripts/harness/agent-integration/application/usecases/get-open-world-obligations-context-usecase.ts +66 -0
  25. package/scripts/harness/agent-integration/infrastructure/adapters/world-model-open-obligations-query-adapter.ts +58 -0
  26. package/scripts/harness/agent-integration/presentation/session-start-hook.ts +37 -1
  27. package/scripts/harness/agent-integration/presentation/world-obligations-session-context.ts +60 -0
  28. package/scripts/harness/attestation/application/dto/attestation-document.ts +17 -4
  29. package/scripts/harness/attestation/application/mappers/attestation-record-mapper.ts +55 -4
  30. package/scripts/harness/attestation/application/ports/sha256-capability.ts +25 -0
  31. package/scripts/harness/attestation/application/ports/world-snapshot-root-provider.ts +10 -0
  32. package/scripts/harness/attestation/application/usecases/produce-attestation-usecase.ts +33 -7
  33. package/scripts/harness/attestation/composition-root.ts +19 -4
  34. package/scripts/harness/attestation/domain/entities/attestation-record.ts +37 -2
  35. package/scripts/harness/attestation/index.ts +13 -2
  36. package/scripts/harness/attestation/infrastructure/adapters/node-crypto-content-hasher-adapter.ts +6 -6
  37. package/scripts/harness/attestation/infrastructure/adapters/node-crypto-sha256-capability.ts +19 -0
  38. package/scripts/harness/attestation/presentation/handlers/attest-handler.ts +5 -2
  39. package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +35 -8
  40. package/scripts/harness/config-foundation/application/mappers/world-model-config-mapper.ts +15 -0
  41. package/scripts/harness/config-foundation/domain/harness-config.ts +67 -87
  42. package/scripts/harness/config-foundation/domain/services/preset-resolution-service.ts +77 -88
  43. package/scripts/harness/config-foundation/domain/value-objects/world-config.ts +198 -0
  44. package/scripts/harness/config-foundation/index.ts +14 -15
  45. package/scripts/harness/config-foundation/infrastructure/presets/minimal.json +24 -0
  46. package/scripts/harness/config-foundation/infrastructure/presets/standard.json +24 -0
  47. package/scripts/harness/config-foundation/infrastructure/presets/strict.json +24 -0
  48. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +83 -0
  49. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +83 -0
  50. package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +18 -4
  51. package/scripts/harness/harness-api/domain/value-objects/known-harness-commands.ts +4 -1
  52. package/scripts/harness/integrations/pre-commit.ts +169 -27
  53. package/scripts/harness/main.ts +276 -126
  54. package/scripts/harness/nyquist-validation/application/dto/generate-matrix-output.ts +11 -0
  55. package/scripts/harness/nyquist-validation/application/usecases/check-ac-coverage-gate-usecase.ts +6 -0
  56. package/scripts/harness/nyquist-validation/application/usecases/generate-requirement-test-matrix-usecase.ts +8 -4
  57. package/scripts/harness/nyquist-validation/domain/entities/story-mapping.ts +29 -2
  58. package/scripts/harness/nyquist-validation/domain/services/ac-coverage-gate-policy.ts +28 -0
  59. package/scripts/harness/nyquist-validation/infrastructure/adapters/markdown-requirement-source-adapter.ts +71 -4
  60. package/scripts/harness/nyquist-validation/infrastructure/schema/matrix-schema-loader.ts +4 -0
  61. package/scripts/harness/traceability-model/application/dto/changed-design-fragment-dto.ts +31 -0
  62. package/scripts/harness/traceability-model/application/dto/traceability-world-read-dto.ts +67 -0
  63. package/scripts/harness/traceability-model/application/facades/design-change-read-facade.ts +14 -0
  64. package/scripts/harness/traceability-model/application/facades/traceability-world-read-facade.ts +372 -0
  65. package/scripts/harness/traceability-model/application/ports/staged-design-change-source-port.ts +9 -0
  66. package/scripts/harness/traceability-model/application/ports/traceability-world-read-source-port.ts +61 -0
  67. package/scripts/harness/traceability-model/composition-root.ts +26 -5
  68. package/scripts/harness/traceability-model/index.ts +26 -6
  69. package/scripts/harness/traceability-model/infrastructure/adapters/file-system-traceability-world-read-adapter.ts +223 -0
  70. package/scripts/harness/traceability-model/infrastructure/adapters/git-staged-design-change-adapter.ts +155 -0
  71. package/scripts/harness/traceability-model/infrastructure/parsers/story-catalog-parser.ts +86 -8
  72. package/scripts/harness/validator-system/application/use-cases/run-l2-validators-usecase.ts +31 -0
  73. package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +34 -0
  74. package/scripts/harness/validator-system/composition-root.ts +21 -6
  75. package/scripts/harness/validator-system/domain/ports/world-constraint-admission-policy-port.ts +28 -0
  76. package/scripts/harness/validator-system/domain/ports/world-constraint-rederivation-policy-port.ts +11 -0
  77. package/scripts/harness/validator-system/domain/services/design-change-declaration-policy.ts +75 -0
  78. package/scripts/harness/validator-system/domain/services/world-constraint-admission-service.ts +78 -0
  79. package/scripts/harness/validator-system/domain/services/world-constraint-rederivation-service.ts +76 -0
  80. package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +4 -0
  81. package/scripts/harness/validator-system/infrastructure/adapters/harness-config-validator-config-adapter.ts +38 -16
  82. package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-admission-adapter.ts +56 -0
  83. package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-rederivation-adapter.ts +56 -0
  84. package/scripts/harness/world-model/application/dto/pinned-design-endpoint-dto.ts +19 -0
  85. package/scripts/harness/world-model/application/dto/world-inspection-dto.ts +43 -0
  86. package/scripts/harness/world-model/application/dto/world-obligation-report-dto.ts +54 -0
  87. package/scripts/harness/world-model/application/dto/world-resolved-config-input.ts +127 -0
  88. package/scripts/harness/world-model/application/dto/world-snapshot-root-dto.ts +8 -0
  89. package/scripts/harness/world-model/application/facades/pinned-design-endpoint-facade.ts +63 -0
  90. package/scripts/harness/world-model/application/facades/world-snapshot-root-facade.ts +19 -0
  91. package/scripts/harness/world-model/application/ports/obligation-report-writer-port.ts +7 -0
  92. package/scripts/harness/world-model/application/ports/world-control-declaration-repository-port.ts +57 -0
  93. package/scripts/harness/world-model/application/ports/world-fact-source-port.ts +17 -0
  94. package/scripts/harness/world-model/application/usecases/build-snapshot-use-case.ts +111 -0
  95. package/scripts/harness/world-model/application/usecases/derive-obligations-use-case.ts +155 -0
  96. package/scripts/harness/world-model/application/usecases/derive-world-obligations-use-case.ts +146 -0
  97. package/scripts/harness/world-model/application/usecases/inspect-world-use-case.ts +74 -0
  98. package/scripts/harness/world-model/application/usecases/pin-constraint-endpoint-use-case.ts +139 -0
  99. package/scripts/harness/world-model/composition-root.ts +247 -0
  100. package/scripts/harness/world-model/domain/entities/constraint-record.ts +148 -0
  101. package/scripts/harness/world-model/domain/entities/control-declarations.ts +274 -0
  102. package/scripts/harness/world-model/domain/entities/edge.ts +41 -0
  103. package/scripts/harness/world-model/domain/entities/extraction-diagnostic.ts +60 -0
  104. package/scripts/harness/world-model/domain/entities/snapshot.ts +75 -0
  105. package/scripts/harness/world-model/domain/entities/world-node.ts +210 -0
  106. package/scripts/harness/world-model/domain/ports/world-hashing-port.ts +8 -0
  107. package/scripts/harness/world-model/domain/services/canonical-json-serializer.ts +113 -0
  108. package/scripts/harness/world-model/domain/services/constraint-evaluator.ts +486 -0
  109. package/scripts/harness/world-model/domain/services/obligation-derivation-service.ts +199 -0
  110. package/scripts/harness/world-model/domain/services/policy-inputs-digest-deriver.ts +66 -0
  111. package/scripts/harness/world-model/domain/services/snapshot-root-deriver.ts +218 -0
  112. package/scripts/harness/world-model/domain/services/text-content-normalizer.ts +30 -0
  113. package/scripts/harness/world-model/domain/services/violation-fingerprint-deriver.ts +183 -0
  114. package/scripts/harness/world-model/domain/value-objects/artifact-kind.ts +58 -0
  115. package/scripts/harness/world-model/domain/value-objects/change-provenance.ts +137 -0
  116. package/scripts/harness/world-model/domain/value-objects/corpus-role.ts +57 -0
  117. package/scripts/harness/world-model/domain/value-objects/declared-key.ts +35 -0
  118. package/scripts/harness/world-model/domain/value-objects/evaluation-id.ts +41 -0
  119. package/scripts/harness/world-model/domain/value-objects/explicit-constraint-relation.ts +53 -0
  120. package/scripts/harness/world-model/domain/value-objects/explicit-node-alias.ts +30 -0
  121. package/scripts/harness/world-model/domain/value-objects/node-pin.ts +34 -0
  122. package/scripts/harness/world-model/domain/value-objects/path-key.ts +103 -0
  123. package/scripts/harness/world-model/domain/value-objects/sha256-digest.ts +39 -0
  124. package/scripts/harness/world-model/domain/value-objects/violation-fingerprint.ts +36 -0
  125. package/scripts/harness/world-model/domain/value-objects/wcr-rule-id.ts +59 -0
  126. package/scripts/harness/world-model/domain/value-objects/world-node-id.ts +222 -0
  127. package/scripts/harness/world-model/index.ts +33 -0
  128. package/scripts/harness/world-model/infrastructure/adapters/adr-fact-extractor.ts +27 -0
  129. package/scripts/harness/world-model/infrastructure/adapters/assembled-world-fact-source.ts +17 -0
  130. package/scripts/harness/world-model/infrastructure/adapters/attestation-fact-extractor.ts +323 -0
  131. package/scripts/harness/world-model/infrastructure/adapters/attestation-sha256-world-hashing-adapter.ts +15 -0
  132. package/scripts/harness/world-model/infrastructure/adapters/composite-design-fact-source.ts +23 -0
  133. package/scripts/harness/world-model/infrastructure/adapters/design-corpus-fact-extractor.ts +285 -0
  134. package/scripts/harness/world-model/infrastructure/adapters/design-fact-extraction.ts +63 -0
  135. package/scripts/harness/world-model/infrastructure/adapters/file-system-obligation-report-writer-adapter.ts +37 -0
  136. package/scripts/harness/world-model/infrastructure/adapters/file-system-world-control-repository-adapters.ts +332 -0
  137. package/scripts/harness/world-model/infrastructure/adapters/integrity-manifest-fact-extractor.ts +101 -0
  138. package/scripts/harness/world-model/infrastructure/adapters/json-fact-extractor-support.ts +151 -0
  139. package/scripts/harness/world-model/infrastructure/adapters/markdown-design-fact-extractor.ts +493 -0
  140. package/scripts/harness/world-model/infrastructure/adapters/matrix-fact-extractor.ts +283 -0
  141. package/scripts/harness/world-model/infrastructure/adapters/product-fact-extractor.ts +29 -0
  142. package/scripts/harness/world-model/infrastructure/adapters/proposal-fact-extractor.ts +29 -0
  143. package/scripts/harness/world-model/infrastructure/adapters/runtime-fact-extraction.ts +19 -0
  144. package/scripts/harness/world-model/infrastructure/adapters/source-metadata-fact-extractor.ts +22 -0
  145. package/scripts/harness/world-model/infrastructure/adapters/test-reference-source-fact-extractor.ts +22 -0
  146. package/scripts/harness/world-model/infrastructure/adapters/traceability-design-fact-adapter.ts +112 -0
  147. package/scripts/harness/world-model/infrastructure/adapters/traceability-world-read-facade-merger.ts +38 -0
  148. package/scripts/harness/world-model/infrastructure/adapters/type-script-source-fact-extractor.ts +236 -0
  149. package/scripts/harness/world-model/infrastructure/adapters/unit-fact-extractor.ts +71 -0
  150. package/scripts/harness/world-model/infrastructure/adapters/world-control-declaration-mapper.ts +383 -0
  151. package/scripts/harness/world-model/presentation/cli/world-command-support.ts +60 -0
  152. package/scripts/harness/world-model/presentation/cli/world-derive-command-handler.ts +109 -0
  153. package/scripts/harness/world-model/presentation/cli/world-inspect-command-handler.ts +194 -0
  154. package/scripts/harness/world-model/presentation/cli/world-pin-command-handler.ts +100 -0
@@ -1,23 +1,28 @@
1
1
  // @unit attestation
2
2
  // @layer application
3
+ // @work-item-id WI-306
3
4
 
4
5
  import { AttestationRecord, type GateResult, type SourceEntry } from "../../domain/entities/attestation-record.js";
5
6
  import type { ContentHasherPort } from "../../domain/ports/content-hasher-port.js";
6
- import type { GranularityDerivationService } from "../../domain/services/granularity-derivation-service.js";
7
7
  import type { AcBoundScopeService } from "../../domain/services/ac-bound-scope-service.js";
8
+ import type { GranularityDerivationService } from "../../domain/services/granularity-derivation-service.js";
9
+ import { Digest } from "../../domain/value-objects/digest.js";
8
10
  import { SignatureBlock } from "../../domain/value-objects/signature-block.js";
9
11
  import { ValidatorOutcome } from "../../domain/value-objects/validator-outcome.js";
10
12
  import type { AttestationDocument } from "../dto/attestation-document.js";
11
13
  import type { ProduceAttestationInput } from "../dto/produce-attestation-input.js";
12
14
  import type { AttestationRecordMapper } from "../mappers/attestation-record-mapper.js";
15
+ import type { AcBoundAllowlistPort } from "../ports/ac-bound-allowlist-port.js";
13
16
  import type { AttestationRepositoryPort } from "../ports/attestation-repository-port.js";
14
17
  import type { GateResultSourcePort } from "../ports/gate-result-source-port.js";
15
- import type { SourceDigesterPort } from "../ports/source-digester-port.js";
16
18
  import type { MatrixSourcePort } from "../ports/matrix-source-port.js";
17
- import type { AcBoundAllowlistPort } from "../ports/ac-bound-allowlist-port.js";
19
+ import type { SourceDigesterPort } from "../ports/source-digester-port.js";
20
+ import type { WorldSnapshotRootProvider } from "../ports/world-snapshot-root-provider.js";
18
21
 
19
- const SCHEMA_VERSION = "phasegate-attestation/v1";
20
- const PREDICATE_TYPE = "https://phasegate.dev/attestation/gate-run/v1";
22
+ const V1_SCHEMA_VERSION = "phasegate-attestation/v1";
23
+ const V1_PREDICATE_TYPE = "https://phasegate.dev/attestation/gate-run/v1";
24
+ const V2_SCHEMA_VERSION = "phasegate-attestation/v2";
25
+ const V2_PREDICATE_TYPE = "https://phasegate.dev/attestation/gate-run/v2";
21
26
  const DEFAULT_INPUT_SOURCES: readonly string[] = Object.freeze([
22
27
  "phasegate.config.json",
23
28
  ".harness/requirement-test-matrix.json",
@@ -46,11 +51,14 @@ export interface ProduceAttestationDeps {
46
51
  readonly acBoundScopeService?: AcBoundScopeService;
47
52
  /** H16-03: matrix 供給元パス(inputSourcePaths のうち matrix にあたるもの。既定は 2 番目の source)。 */
48
53
  readonly matrixFilePath?: string;
54
+ /** WI-306: 配線時はv2、未配線時は既存v1を生成する。 */
55
+ readonly worldSnapshotRootProvider?: WorldSnapshotRootProvider;
49
56
  }
50
57
 
51
58
  export interface ProduceAttestationResult {
52
59
  readonly document: AttestationDocument | null;
53
60
  readonly exitCode: 0 | 1 | 2;
61
+ readonly error?: string;
54
62
  }
55
63
 
56
64
  /**
@@ -77,6 +85,20 @@ export class ProduceAttestationUseCase {
77
85
  return { document: null, exitCode: 1 };
78
86
  }
79
87
 
88
+ // 3b. World root providerはv2 opt-in。失敗や不正digestをv1へdowngradeしない。
89
+ let worldSnapshotRoot: Digest | undefined;
90
+ if (this.deps.worldSnapshotRootProvider) {
91
+ try {
92
+ worldSnapshotRoot = Digest.create(await this.deps.worldSnapshotRootProvider.getWorldSnapshotRoot());
93
+ } catch (error) {
94
+ return {
95
+ document: null,
96
+ exitCode: 2,
97
+ error: `cannot obtain worldSnapshotRoot: ${error instanceof Error ? error.message : String(error)}`,
98
+ };
99
+ }
100
+ }
101
+
80
102
  // 4. inputs.sources 構築(config / matrix の sha256 + git commit SHA)と inputDigest 算出
81
103
  const sources = await this.buildSources();
82
104
  const preInputRecord = this.assembleRecord({
@@ -88,6 +110,7 @@ export class ProduceAttestationUseCase {
88
110
  producer: `phasegate-attestation/${this.deps.pkgVersion}`,
89
111
  gitCommit: null,
90
112
  acBoundScope: [],
113
+ worldSnapshotRoot,
91
114
  });
92
115
  const inputDigest = preInputRecord.computeInputDigest(this.deps.hasher);
93
116
 
@@ -110,6 +133,7 @@ export class ProduceAttestationUseCase {
110
133
  producer: `phasegate-attestation/${this.deps.pkgVersion}`,
111
134
  gitCommit,
112
135
  acBoundScope,
136
+ worldSnapshotRoot,
113
137
  });
114
138
  const sealed = record.seal(this.deps.hasher);
115
139
 
@@ -130,11 +154,12 @@ export class ProduceAttestationUseCase {
130
154
  producer: string;
131
155
  gitCommit: string | null;
132
156
  acBoundScope: readonly string[];
157
+ worldSnapshotRoot?: Digest;
133
158
  }): AttestationRecord {
134
159
  const granularity = this.deps.granularityService.derive(args.validatorSet);
135
160
  return AttestationRecord.create({
136
- schemaVersion: SCHEMA_VERSION,
137
- predicateType: PREDICATE_TYPE,
161
+ schemaVersion: args.worldSnapshotRoot ? V2_SCHEMA_VERSION : V1_SCHEMA_VERSION,
162
+ predicateType: args.worldSnapshotRoot ? V2_PREDICATE_TYPE : V1_PREDICATE_TYPE,
138
163
  subject: {
139
164
  command: "phasegate:ci-check",
140
165
  gateResult: args.gateResult,
@@ -154,6 +179,7 @@ export class ProduceAttestationUseCase {
154
179
  // 仮の unsigned-poc block(seal 前)。seal が正しい digest で置換する。
155
180
  signature: SignatureBlock.unsignedPoc(args.inputDigest),
156
181
  acBoundScope: args.acBoundScope,
182
+ ...(args.worldSnapshotRoot ? { worldSnapshotRoot: args.worldSnapshotRoot } : {}),
157
183
  });
158
184
  }
159
185
 
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * @layer infrastructure
3
3
  * @unit attestation
4
+ * @work-item-id WI-306
4
5
  *
5
6
  * Composition Root — attestation Unit の依存性組み立て。
6
7
  * createAttestationModule() は adapters + usecases + handlers を組み立て、
@@ -10,16 +11,19 @@
10
11
  import { execFile } from "node:child_process";
11
12
  import { promisify } from "node:util";
12
13
  import { AttestationRecordMapper } from "./application/mappers/attestation-record-mapper.js";
14
+ import type { Sha256Capability } from "./application/ports/sha256-capability.js";
15
+ import type { WorldSnapshotRootProvider } from "./application/ports/world-snapshot-root-provider.js";
13
16
  import { ProduceAttestationUseCase } from "./application/usecases/produce-attestation-usecase.js";
14
17
  import { VerifyAttestationUseCase } from "./application/usecases/verify-attestation-usecase.js";
15
- import { GranularityDerivationService } from "./domain/services/granularity-derivation-service.js";
16
18
  import { AcBoundScopeService } from "./domain/services/ac-bound-scope-service.js";
19
+ import { GranularityDerivationService } from "./domain/services/granularity-derivation-service.js";
17
20
  import { CiCheckGateResultAdapter } from "./infrastructure/adapters/ci-check-gate-result-adapter.js";
21
+ import { ConfigAcBoundAllowlistAdapter } from "./infrastructure/adapters/config-ac-bound-allowlist-adapter.js";
18
22
  import { FileSystemAttestationRepositoryAdapter } from "./infrastructure/adapters/file-system-attestation-repository-adapter.js";
19
- import { FileSystemSourceDigesterAdapter } from "./infrastructure/adapters/file-system-source-digester-adapter.js";
20
23
  import { FileSystemMatrixSourceAdapter } from "./infrastructure/adapters/file-system-matrix-source-adapter.js";
21
- import { ConfigAcBoundAllowlistAdapter } from "./infrastructure/adapters/config-ac-bound-allowlist-adapter.js";
24
+ import { FileSystemSourceDigesterAdapter } from "./infrastructure/adapters/file-system-source-digester-adapter.js";
22
25
  import { NodeCryptoContentHasherAdapter } from "./infrastructure/adapters/node-crypto-content-hasher-adapter.js";
26
+ import { NodeCryptoSha256Capability } from "./infrastructure/adapters/node-crypto-sha256-capability.js";
23
27
  import { AttestHandler } from "./presentation/handlers/attest-handler.js";
24
28
  import { VerifyAttestationHandler } from "./presentation/handlers/verify-attestation-handler.js";
25
29
 
@@ -39,6 +43,15 @@ export interface AttestationModuleOptions {
39
43
  readonly mainTsPath?: string;
40
44
  /** metadata.producedAt 用クロックのオーバーライド(テスト用)。 */
41
45
  readonly clock?: () => Date;
46
+ /** WI-306: 配線時はv2 recordへplain World corpus rootを注入する。 */
47
+ readonly worldSnapshotRootProvider?: WorldSnapshotRootProvider;
48
+ }
49
+
50
+ /**
51
+ * Unit非依存のplain SHA-256 public capabilityを生成する。
52
+ */
53
+ export function createSha256Capability(): Sha256Capability {
54
+ return new NodeCryptoSha256Capability();
42
55
  }
43
56
 
44
57
  /**
@@ -47,7 +60,8 @@ export interface AttestationModuleOptions {
47
60
  */
48
61
  export function createAttestationModule(rootDir: string, options?: AttestationModuleOptions): AttestationModule {
49
62
  // Infrastructure adapters
50
- const hasher = new NodeCryptoContentHasherAdapter();
63
+ const sha256Capability = createSha256Capability();
64
+ const hasher = new NodeCryptoContentHasherAdapter(sha256Capability);
51
65
  const sourceDigester = new FileSystemSourceDigesterAdapter(rootDir);
52
66
  const gateResultSource = new CiCheckGateResultAdapter({ mainTsPath: options?.mainTsPath });
53
67
  const repository = new FileSystemAttestationRepositoryAdapter(rootDir);
@@ -77,6 +91,7 @@ export function createAttestationModule(rootDir: string, options?: AttestationMo
77
91
  matrixSource,
78
92
  allowlist,
79
93
  acBoundScopeService,
94
+ worldSnapshotRootProvider: options?.worldSnapshotRootProvider,
80
95
  });
81
96
  const verifyUseCase = new VerifyAttestationUseCase({
82
97
  repository,
@@ -1,5 +1,6 @@
1
1
  // @unit attestation
2
2
  // @layer domain
3
+ // @work-item-id WI-306
3
4
 
4
5
  import type { ContentHasherPort } from "../ports/content-hasher-port.js";
5
6
  import { GranularityDerivationService } from "../services/granularity-derivation-service.js";
@@ -47,6 +48,8 @@ export interface AttestationRecordProps {
47
48
  * 省略時は [] として扱う(additive-safe)。
48
49
  */
49
50
  readonly acBoundScope?: readonly string[];
51
+ /** v2だけが持つ実行時World corpus root。 */
52
+ readonly worldSnapshotRoot?: Digest;
50
53
  }
51
54
 
52
55
  /**
@@ -94,6 +97,7 @@ export class AttestationRecord {
94
97
  readonly metadata: MetadataSection;
95
98
  readonly signature: SignatureBlock;
96
99
  readonly acBoundScope: readonly string[];
100
+ readonly worldSnapshotRoot: Digest | null;
97
101
 
98
102
  private constructor(props: AttestationRecordProps) {
99
103
  this.schemaVersion = props.schemaVersion;
@@ -104,10 +108,12 @@ export class AttestationRecord {
104
108
  this.metadata = props.metadata;
105
109
  this.signature = props.signature;
106
110
  this.acBoundScope = Object.freeze([...(props.acBoundScope ?? [])]);
111
+ this.worldSnapshotRoot = props.worldSnapshotRoot ?? null;
107
112
  Object.freeze(this);
108
113
  }
109
114
 
110
115
  static create(props: AttestationRecordProps): AttestationRecord {
116
+ AttestationRecord.assertVersionContract(props);
111
117
  // INV-1: gateResult == "pass" iff validatorSet.every(passed || skipped)
112
118
  const allGreen = props.subject.validatorSet.every((o) => o.isGreen());
113
119
  const expectedGateResult: GateResult = allGreen ? "pass" : "fail";
@@ -149,6 +155,22 @@ export class AttestationRecord {
149
155
  return new AttestationRecord(props);
150
156
  }
151
157
 
158
+ private static assertVersionContract(props: AttestationRecordProps): void {
159
+ const v1 =
160
+ props.schemaVersion === "phasegate-attestation/v1" &&
161
+ props.predicateType === "https://phasegate.dev/attestation/gate-run/v1" &&
162
+ props.worldSnapshotRoot === undefined;
163
+ const v2 =
164
+ props.schemaVersion === "phasegate-attestation/v2" &&
165
+ props.predicateType === "https://phasegate.dev/attestation/gate-run/v2" &&
166
+ props.worldSnapshotRoot !== undefined;
167
+ if (!v1 && !v2) {
168
+ throw new AttestationInvariantError(
169
+ "version contract violated: schema, predicate, and worldSnapshotRoot disagree",
170
+ );
171
+ }
172
+ }
173
+
152
174
  gateResult(): GateResult {
153
175
  return this.subject.gateResult;
154
176
  }
@@ -165,10 +187,9 @@ export class AttestationRecord {
165
187
 
166
188
  /**
167
189
  * §1.4.1 step1-3: signature ブロック全体と volatile metadata(producedAt/gitCommit)を
168
- * 除去した plain object を返す(producer は決定論的なので残す)。
169
190
  */
170
191
  toCanonicalPayload(): Record<string, unknown> {
171
- return {
192
+ const payload: Record<string, unknown> = {
172
193
  schemaVersion: this.schemaVersion,
173
194
  predicateType: this.predicateType,
174
195
  subject: {
@@ -199,6 +220,10 @@ export class AttestationRecord {
199
220
  producer: this.metadata.producer,
200
221
  },
201
222
  };
223
+ if (this.worldSnapshotRoot !== null) {
224
+ payload.worldSnapshotRoot = this.worldSnapshotRoot.value;
225
+ }
226
+ return payload;
202
227
  }
203
228
 
204
229
  /**
@@ -222,6 +247,7 @@ export class AttestationRecord {
222
247
  metadata: this.metadata,
223
248
  signature: SignatureBlock.unsignedPoc(digest),
224
249
  acBoundScope: this.acBoundScope,
250
+ ...(this.worldSnapshotRoot === null ? {} : { worldSnapshotRoot: this.worldSnapshotRoot }),
225
251
  });
226
252
  }
227
253
 
@@ -247,6 +273,15 @@ export class AttestationRecord {
247
273
  if (!this.granularity.traceability.equals(other.granularity.traceability)) return false;
248
274
  if (this.acBoundScope.length !== other.acBoundScope.length) return false;
249
275
  if (!this.acBoundScope.every((s, i) => s === other.acBoundScope[i])) return false;
276
+ if (this.worldSnapshotRoot === null && other.worldSnapshotRoot !== null) return false;
277
+ if (this.worldSnapshotRoot !== null && other.worldSnapshotRoot === null) return false;
278
+ if (
279
+ this.worldSnapshotRoot !== null &&
280
+ other.worldSnapshotRoot !== null &&
281
+ !this.worldSnapshotRoot.equals(other.worldSnapshotRoot)
282
+ ) {
283
+ return false;
284
+ }
250
285
  if (!this.signature.equals(other.signature)) return false;
251
286
  return true;
252
287
  }
@@ -1,13 +1,24 @@
1
1
  // @layer infrastructure
2
2
  // @unit attestation
3
+ // @work-item-id WI-306
3
4
  // index.ts — attestation Unit の公開バレルエクスポート
4
5
 
5
6
  // Public DTO types
6
- export type { AttestationDocument } from "./application/dto/attestation-document.js";
7
+ export type {
8
+ AttestationDocument,
9
+ AttestationDocumentV1,
10
+ AttestationDocumentV2,
11
+ } from "./application/dto/attestation-document.js";
7
12
  export type { VerifyAttestationOutput } from "./application/dto/verify-attestation-output.js";
13
+ export {
14
+ hashUtf8,
15
+ type Sha256Capability,
16
+ type Sha256DigestString,
17
+ } from "./application/ports/sha256-capability.js";
18
+ export type { WorldSnapshotRootProvider } from "./application/ports/world-snapshot-root-provider.js";
8
19
  export type { AttestationModule, AttestationModuleOptions } from "./composition-root.js";
9
20
  // Composition Root
10
- export { createAttestationModule } from "./composition-root.js";
21
+ export { createAttestationModule, createSha256Capability } from "./composition-root.js";
11
22
  export type { AttestHandlerArgs, AttestHandlerResult } from "./presentation/handlers/attest-handler.js";
12
23
  // Presentation Handlers
13
24
  export { AttestHandler } from "./presentation/handlers/attest-handler.js";
@@ -1,18 +1,18 @@
1
1
  // @unit attestation
2
2
  // @layer infrastructure
3
3
 
4
- import { createHash } from "node:crypto";
4
+ import { hashUtf8, type Sha256Capability } from "../../application/ports/sha256-capability.js";
5
5
  import type { ContentHasherPort } from "../../domain/ports/content-hasher-port.js";
6
6
  import { Digest } from "../../domain/value-objects/digest.js";
7
+ import { NodeCryptoSha256Capability } from "./node-crypto-sha256-capability.js";
7
8
 
8
9
  /**
9
- * ContentHasherPort node:crypto 実装。
10
- * canonical payload / source content の sha256 を `sha256:<64hex>` Digest として返す。
11
- * installation の node-crypto-hash-adapter をミラーし、アルゴリズムは sha256 に固定する。
10
+ * Public Sha256Capabilityをattestation-local ContentHasherPortへ変換するadapter。
12
11
  */
13
12
  export class NodeCryptoContentHasherAdapter implements ContentHasherPort {
13
+ constructor(private readonly capability: Sha256Capability = new NodeCryptoSha256Capability()) {}
14
+
14
15
  sha256(content: string): Digest {
15
- const hex = createHash("sha256").update(content, "utf8").digest("hex");
16
- return Digest.fromSha256Hex(hex);
16
+ return Digest.create(hashUtf8(this.capability, content));
17
17
  }
18
18
  }
@@ -0,0 +1,19 @@
1
+ // @unit attestation
2
+ // @layer infrastructure
3
+ // @work-item-id WI-286
4
+
5
+ import { createHash } from "node:crypto";
6
+ import type { Sha256Capability, Sha256DigestString } from "../../application/ports/sha256-capability.js";
7
+
8
+ /**
9
+ * Attestation public SHA-256 capabilityのNode.js実装。
10
+ *
11
+ * 既存NodeCryptoContentHasherAdapterからprimitiveを移動し、
12
+ * World向けにnode:crypto call siteを増やさない。
13
+ */
14
+ export class NodeCryptoSha256Capability implements Sha256Capability {
15
+ hashBytes(bytes: Uint8Array): Sha256DigestString {
16
+ const hex = createHash("sha256").update(bytes).digest("hex");
17
+ return `sha256:${hex}`;
18
+ }
19
+ }
@@ -1,5 +1,6 @@
1
1
  // @unit attestation
2
2
  // @layer presentation
3
+ // @work-item-id WI-306
3
4
 
4
5
  import type { ProduceAttestationInput } from "../../application/dto/produce-attestation-input.js";
5
6
  import type { ProduceAttestationUseCase } from "../../application/usecases/produce-attestation-usecase.js";
@@ -46,8 +47,10 @@ export class AttestHandler {
46
47
  const result = await this.useCase.execute(input);
47
48
 
48
49
  if (result.exitCode === 2) {
49
- // 唯一の usecase 由来 2 は mode === "signed"。
50
- return { output: 'Error: --mode "signed" is not yet implemented (only unsigned-poc is supported)', exitCode: 2 };
50
+ const output = result.error
51
+ ? `Error: ${result.error}`
52
+ : 'Error: --mode "signed" is not yet implemented (only unsigned-poc is supported)';
53
+ return { output, exitCode: 2 };
51
54
  }
52
55
 
53
56
  if (result.exitCode === 1) {
@@ -7,6 +7,9 @@
7
7
  * @work-item-id WI-258
8
8
  * @work-item-id WI-259
9
9
  * @work-item-id WI-268
10
+ * @work-item-id WI-300
11
+ * @work-item-id WI-301
12
+ * @work-item-id WI-302
10
13
  */
11
14
  import type { HarnessConfigV2 } from "../../domain/harness-config.js";
12
15
 
@@ -23,6 +26,7 @@ export function toValidatorSystemConfig(resolvedConfig: HarnessConfigV2 | undefi
23
26
  "ac-bound-coverage": "L3-005",
24
27
  "injection-scan": "L3-006",
25
28
  "coverage-attestation-verification": "L3-007",
29
+ "world-constraint-rederivation": "L3-008",
26
30
  },
27
31
  /^L3-\d{3}$/,
28
32
  );
@@ -60,7 +64,10 @@ export function toValidatorSystemConfig(resolvedConfig: HarnessConfigV2 | undefi
60
64
  // WI-258 / ADR-030 §Decision.3.②: L2-016 (coverage-attestation-gating) を default-ON でリストに含める。
61
65
  L2: {
62
66
  enabled: resolvedConfig.layers.L2.enabled,
63
- validators: ["L2-001", "L2-002", "L2-003", "L2-013", "L2-014", "L2-015", "L2-016"],
67
+ validators:
68
+ resolvedConfig.world?.enabled === true
69
+ ? ["L2-001", "L2-002", "L2-003", "L2-013", "L2-014", "L2-015", "L2-016", "L2-017"]
70
+ : ["L2-001", "L2-002", "L2-003", "L2-013", "L2-014", "L2-015", "L2-016"],
64
71
  },
65
72
  L3: {
66
73
  enabled: resolvedConfig.layers.L3.enabled,
@@ -68,13 +75,28 @@ export function toValidatorSystemConfig(resolvedConfig: HarnessConfigV2 | undefi
68
75
  // WI-268 / ADR-030 §Decision.1・§Decision.3.② 第2段: L3-007 (coverage-attestation-verification)
69
76
  // は fail-closed default-ON。いずれも fallback 判定の後に force-include し、normalize 結果でも
70
77
  // fallback でも常に含める(L3-007 は fail-closed だが現 corpus は実参照 0 件ゆえ緑)。
71
- validators: includeValidator(
72
- includeValidator(
73
- l3Validators.length > 0 ? l3Validators : ["L3-001", "L3-002", "L3-003", "L3-004"],
74
- "L3-006",
75
- ),
76
- "L3-007",
77
- ),
78
+ validators:
79
+ resolvedConfig.world?.enabled === true
80
+ ? includeValidator(
81
+ includeValidator(
82
+ includeValidator(
83
+ l3Validators.length > 0 ? l3Validators : ["L3-001", "L3-002", "L3-003", "L3-004"],
84
+ "L3-006",
85
+ ),
86
+ "L3-007",
87
+ ),
88
+ "L3-008",
89
+ )
90
+ : excludeValidator(
91
+ includeValidator(
92
+ includeValidator(
93
+ l3Validators.length > 0 ? l3Validators : ["L3-001", "L3-002", "L3-003", "L3-004"],
94
+ "L3-006",
95
+ ),
96
+ "L3-007",
97
+ ),
98
+ "L3-008",
99
+ ),
78
100
  coverageThreshold: resolvedConfig.layers.L3.coverageThreshold,
79
101
  requirementMatrixPath: resolvedConfig.layers.L3.requirementMatrixPath,
80
102
  // WI-227 / H16-03: L3-005 のスコープ(additive-safe。未設定は [])
@@ -96,6 +118,7 @@ export function toValidatorSystemConfig(resolvedConfig: HarnessConfigV2 | undefi
96
118
  validate: {
97
119
  failOnWarning: resolvedConfig.validate.failOnWarning,
98
120
  },
121
+ ...(resolvedConfig.world === undefined ? {} : { world: structuredClone(resolvedConfig.world) }),
99
122
  };
100
123
  }
101
124
 
@@ -110,6 +133,10 @@ function includeValidator(validators: readonly string[], validatorId: string): r
110
133
  return validators.includes(validatorId) ? validators : [...validators, validatorId];
111
134
  }
112
135
 
136
+ function excludeValidator(validators: readonly string[], validatorId: string): readonly string[] {
137
+ return validators.filter((candidate) => candidate !== validatorId);
138
+ }
139
+
113
140
  function normalizeValidators(
114
141
  validators: readonly string[],
115
142
  aliases: Readonly<Record<string, string>>,
@@ -0,0 +1,15 @@
1
+ // @unit config-foundation
2
+ // @layer application
3
+ // @work-item-id WI-300
4
+
5
+ import type { HarnessConfigV2 } from "../../domain/harness-config.js";
6
+ import {
7
+ WORLD_CONFIG_DEFAULTS,
8
+ WorldConfig,
9
+ type WorldConfigDocument,
10
+ } from "../../domain/value-objects/world-config.js";
11
+
12
+ export function toWorldModelConfig(resolvedConfig: HarnessConfigV2 | undefined): WorldConfigDocument | undefined {
13
+ if (!resolvedConfig) return undefined;
14
+ return WorldConfig.create(resolvedConfig.world ?? WORLD_CONFIG_DEFAULTS).toDocument();
15
+ }