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.
- package/CHANGELOG.md +73 -1
- package/README.ja.md +31 -1
- package/README.md +30 -0
- package/docs/ADR/031-world-model-ownership-and-corpus-lifecycle.md +155 -0
- package/docs/ADR/032-world-node-identity.md +198 -0
- package/docs/ADR/033-world-snapshot-canonicalization.md +246 -0
- package/docs/ADR/034-world-constraint-semantics.md +218 -0
- package/docs/ADR/035-world-adoption-baseline-and-waiver.md +341 -0
- package/docs/ADR/036-world-model-and-doc-freshness.md +169 -0
- package/docs/ADR/037-world-cli-and-output-contract.md +398 -0
- package/docs/contracts/attestation-v2.schema.json +110 -0
- package/docs/contracts/requirement-test-matrix.schema.json +15 -0
- package/docs/contracts/world-baseline.schema.json +35 -0
- package/docs/contracts/world-constraints.schema.json +56 -0
- package/docs/contracts/world-debts.schema.json +32 -0
- package/docs/contracts/world-obligation-report.schema.json +259 -0
- package/docs/contracts/world-waivers.schema.json +32 -0
- package/docs/guide/cli-reference.md +45 -0
- package/docs/guide/configuration.md +56 -0
- package/docs/templates/ci/aidlc-gate.yml +42 -2
- package/package.json +1 -1
- package/scripts/harness/agent-integration/application/dto/open-world-obligations-context-dto.ts +30 -0
- package/scripts/harness/agent-integration/application/ports/world-obligations-query-port.ts +30 -0
- package/scripts/harness/agent-integration/application/usecases/get-open-world-obligations-context-usecase.ts +66 -0
- package/scripts/harness/agent-integration/infrastructure/adapters/world-model-open-obligations-query-adapter.ts +58 -0
- package/scripts/harness/agent-integration/presentation/session-start-hook.ts +37 -1
- package/scripts/harness/agent-integration/presentation/world-obligations-session-context.ts +60 -0
- package/scripts/harness/attestation/application/dto/attestation-document.ts +17 -4
- package/scripts/harness/attestation/application/mappers/attestation-record-mapper.ts +55 -4
- package/scripts/harness/attestation/application/ports/sha256-capability.ts +25 -0
- package/scripts/harness/attestation/application/ports/world-snapshot-root-provider.ts +10 -0
- package/scripts/harness/attestation/application/usecases/produce-attestation-usecase.ts +33 -7
- package/scripts/harness/attestation/composition-root.ts +19 -4
- package/scripts/harness/attestation/domain/entities/attestation-record.ts +37 -2
- package/scripts/harness/attestation/index.ts +13 -2
- package/scripts/harness/attestation/infrastructure/adapters/node-crypto-content-hasher-adapter.ts +6 -6
- package/scripts/harness/attestation/infrastructure/adapters/node-crypto-sha256-capability.ts +19 -0
- package/scripts/harness/attestation/presentation/handlers/attest-handler.ts +5 -2
- package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +35 -8
- package/scripts/harness/config-foundation/application/mappers/world-model-config-mapper.ts +15 -0
- package/scripts/harness/config-foundation/domain/harness-config.ts +67 -87
- package/scripts/harness/config-foundation/domain/services/preset-resolution-service.ts +77 -88
- package/scripts/harness/config-foundation/domain/value-objects/world-config.ts +198 -0
- package/scripts/harness/config-foundation/index.ts +14 -15
- package/scripts/harness/config-foundation/infrastructure/presets/minimal.json +24 -0
- package/scripts/harness/config-foundation/infrastructure/presets/standard.json +24 -0
- package/scripts/harness/config-foundation/infrastructure/presets/strict.json +24 -0
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +83 -0
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +83 -0
- package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +18 -4
- package/scripts/harness/harness-api/domain/value-objects/known-harness-commands.ts +4 -1
- package/scripts/harness/integrations/pre-commit.ts +169 -27
- package/scripts/harness/main.ts +276 -126
- package/scripts/harness/nyquist-validation/application/dto/generate-matrix-output.ts +11 -0
- package/scripts/harness/nyquist-validation/application/usecases/check-ac-coverage-gate-usecase.ts +6 -0
- package/scripts/harness/nyquist-validation/application/usecases/generate-requirement-test-matrix-usecase.ts +8 -4
- package/scripts/harness/nyquist-validation/domain/entities/story-mapping.ts +29 -2
- package/scripts/harness/nyquist-validation/domain/services/ac-coverage-gate-policy.ts +28 -0
- package/scripts/harness/nyquist-validation/infrastructure/adapters/markdown-requirement-source-adapter.ts +71 -4
- package/scripts/harness/nyquist-validation/infrastructure/schema/matrix-schema-loader.ts +4 -0
- package/scripts/harness/traceability-model/application/dto/changed-design-fragment-dto.ts +31 -0
- package/scripts/harness/traceability-model/application/dto/traceability-world-read-dto.ts +67 -0
- package/scripts/harness/traceability-model/application/facades/design-change-read-facade.ts +14 -0
- package/scripts/harness/traceability-model/application/facades/traceability-world-read-facade.ts +372 -0
- package/scripts/harness/traceability-model/application/ports/staged-design-change-source-port.ts +9 -0
- package/scripts/harness/traceability-model/application/ports/traceability-world-read-source-port.ts +61 -0
- package/scripts/harness/traceability-model/composition-root.ts +26 -5
- package/scripts/harness/traceability-model/index.ts +26 -6
- package/scripts/harness/traceability-model/infrastructure/adapters/file-system-traceability-world-read-adapter.ts +223 -0
- package/scripts/harness/traceability-model/infrastructure/adapters/git-staged-design-change-adapter.ts +155 -0
- package/scripts/harness/traceability-model/infrastructure/parsers/story-catalog-parser.ts +86 -8
- package/scripts/harness/validator-system/application/use-cases/run-l2-validators-usecase.ts +31 -0
- package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +34 -0
- package/scripts/harness/validator-system/composition-root.ts +21 -6
- package/scripts/harness/validator-system/domain/ports/world-constraint-admission-policy-port.ts +28 -0
- package/scripts/harness/validator-system/domain/ports/world-constraint-rederivation-policy-port.ts +11 -0
- package/scripts/harness/validator-system/domain/services/design-change-declaration-policy.ts +75 -0
- package/scripts/harness/validator-system/domain/services/world-constraint-admission-service.ts +78 -0
- package/scripts/harness/validator-system/domain/services/world-constraint-rederivation-service.ts +76 -0
- package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +4 -0
- package/scripts/harness/validator-system/infrastructure/adapters/harness-config-validator-config-adapter.ts +38 -16
- package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-admission-adapter.ts +56 -0
- package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-rederivation-adapter.ts +56 -0
- package/scripts/harness/world-model/application/dto/pinned-design-endpoint-dto.ts +19 -0
- package/scripts/harness/world-model/application/dto/world-inspection-dto.ts +43 -0
- package/scripts/harness/world-model/application/dto/world-obligation-report-dto.ts +54 -0
- package/scripts/harness/world-model/application/dto/world-resolved-config-input.ts +127 -0
- package/scripts/harness/world-model/application/dto/world-snapshot-root-dto.ts +8 -0
- package/scripts/harness/world-model/application/facades/pinned-design-endpoint-facade.ts +63 -0
- package/scripts/harness/world-model/application/facades/world-snapshot-root-facade.ts +19 -0
- package/scripts/harness/world-model/application/ports/obligation-report-writer-port.ts +7 -0
- package/scripts/harness/world-model/application/ports/world-control-declaration-repository-port.ts +57 -0
- package/scripts/harness/world-model/application/ports/world-fact-source-port.ts +17 -0
- package/scripts/harness/world-model/application/usecases/build-snapshot-use-case.ts +111 -0
- package/scripts/harness/world-model/application/usecases/derive-obligations-use-case.ts +155 -0
- package/scripts/harness/world-model/application/usecases/derive-world-obligations-use-case.ts +146 -0
- package/scripts/harness/world-model/application/usecases/inspect-world-use-case.ts +74 -0
- package/scripts/harness/world-model/application/usecases/pin-constraint-endpoint-use-case.ts +139 -0
- package/scripts/harness/world-model/composition-root.ts +247 -0
- package/scripts/harness/world-model/domain/entities/constraint-record.ts +148 -0
- package/scripts/harness/world-model/domain/entities/control-declarations.ts +274 -0
- package/scripts/harness/world-model/domain/entities/edge.ts +41 -0
- package/scripts/harness/world-model/domain/entities/extraction-diagnostic.ts +60 -0
- package/scripts/harness/world-model/domain/entities/snapshot.ts +75 -0
- package/scripts/harness/world-model/domain/entities/world-node.ts +210 -0
- package/scripts/harness/world-model/domain/ports/world-hashing-port.ts +8 -0
- package/scripts/harness/world-model/domain/services/canonical-json-serializer.ts +113 -0
- package/scripts/harness/world-model/domain/services/constraint-evaluator.ts +486 -0
- package/scripts/harness/world-model/domain/services/obligation-derivation-service.ts +199 -0
- package/scripts/harness/world-model/domain/services/policy-inputs-digest-deriver.ts +66 -0
- package/scripts/harness/world-model/domain/services/snapshot-root-deriver.ts +218 -0
- package/scripts/harness/world-model/domain/services/text-content-normalizer.ts +30 -0
- package/scripts/harness/world-model/domain/services/violation-fingerprint-deriver.ts +183 -0
- package/scripts/harness/world-model/domain/value-objects/artifact-kind.ts +58 -0
- package/scripts/harness/world-model/domain/value-objects/change-provenance.ts +137 -0
- package/scripts/harness/world-model/domain/value-objects/corpus-role.ts +57 -0
- package/scripts/harness/world-model/domain/value-objects/declared-key.ts +35 -0
- package/scripts/harness/world-model/domain/value-objects/evaluation-id.ts +41 -0
- package/scripts/harness/world-model/domain/value-objects/explicit-constraint-relation.ts +53 -0
- package/scripts/harness/world-model/domain/value-objects/explicit-node-alias.ts +30 -0
- package/scripts/harness/world-model/domain/value-objects/node-pin.ts +34 -0
- package/scripts/harness/world-model/domain/value-objects/path-key.ts +103 -0
- package/scripts/harness/world-model/domain/value-objects/sha256-digest.ts +39 -0
- package/scripts/harness/world-model/domain/value-objects/violation-fingerprint.ts +36 -0
- package/scripts/harness/world-model/domain/value-objects/wcr-rule-id.ts +59 -0
- package/scripts/harness/world-model/domain/value-objects/world-node-id.ts +222 -0
- package/scripts/harness/world-model/index.ts +33 -0
- package/scripts/harness/world-model/infrastructure/adapters/adr-fact-extractor.ts +27 -0
- package/scripts/harness/world-model/infrastructure/adapters/assembled-world-fact-source.ts +17 -0
- package/scripts/harness/world-model/infrastructure/adapters/attestation-fact-extractor.ts +323 -0
- package/scripts/harness/world-model/infrastructure/adapters/attestation-sha256-world-hashing-adapter.ts +15 -0
- package/scripts/harness/world-model/infrastructure/adapters/composite-design-fact-source.ts +23 -0
- package/scripts/harness/world-model/infrastructure/adapters/design-corpus-fact-extractor.ts +285 -0
- package/scripts/harness/world-model/infrastructure/adapters/design-fact-extraction.ts +63 -0
- package/scripts/harness/world-model/infrastructure/adapters/file-system-obligation-report-writer-adapter.ts +37 -0
- package/scripts/harness/world-model/infrastructure/adapters/file-system-world-control-repository-adapters.ts +332 -0
- package/scripts/harness/world-model/infrastructure/adapters/integrity-manifest-fact-extractor.ts +101 -0
- package/scripts/harness/world-model/infrastructure/adapters/json-fact-extractor-support.ts +151 -0
- package/scripts/harness/world-model/infrastructure/adapters/markdown-design-fact-extractor.ts +493 -0
- package/scripts/harness/world-model/infrastructure/adapters/matrix-fact-extractor.ts +283 -0
- package/scripts/harness/world-model/infrastructure/adapters/product-fact-extractor.ts +29 -0
- package/scripts/harness/world-model/infrastructure/adapters/proposal-fact-extractor.ts +29 -0
- package/scripts/harness/world-model/infrastructure/adapters/runtime-fact-extraction.ts +19 -0
- package/scripts/harness/world-model/infrastructure/adapters/source-metadata-fact-extractor.ts +22 -0
- package/scripts/harness/world-model/infrastructure/adapters/test-reference-source-fact-extractor.ts +22 -0
- package/scripts/harness/world-model/infrastructure/adapters/traceability-design-fact-adapter.ts +112 -0
- package/scripts/harness/world-model/infrastructure/adapters/traceability-world-read-facade-merger.ts +38 -0
- package/scripts/harness/world-model/infrastructure/adapters/type-script-source-fact-extractor.ts +236 -0
- package/scripts/harness/world-model/infrastructure/adapters/unit-fact-extractor.ts +71 -0
- package/scripts/harness/world-model/infrastructure/adapters/world-control-declaration-mapper.ts +383 -0
- package/scripts/harness/world-model/presentation/cli/world-command-support.ts +60 -0
- package/scripts/harness/world-model/presentation/cli/world-derive-command-handler.ts +109 -0
- package/scripts/harness/world-model/presentation/cli/world-inspect-command-handler.ts +194 -0
- 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 {
|
|
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
|
|
20
|
-
const
|
|
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:
|
|
137
|
-
predicateType:
|
|
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 {
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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";
|
package/scripts/harness/attestation/infrastructure/adapters/node-crypto-content-hasher-adapter.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
// @unit attestation
|
|
2
2
|
// @layer infrastructure
|
|
3
3
|
|
|
4
|
-
import {
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
50
|
-
|
|
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) {
|
package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts
CHANGED
|
@@ -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:
|
|
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:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
+
}
|