betterwithage Claude Opus 4.7 commited on
Commit
fcc3a97
·
verified ·
1 Parent(s): b40fdf5

deploy(hf): sync szl-holdings/a11oy@2c09e5d7a552802149161edccf55d279e5aaec42 derived COPY set

Browse files

Reusable Dockerfile-COPY-derived deploy from szl-holdings/a11oy 2c09e5d7a552802149161edccf55d279e5aaec42.
Files: 1169 Pruned: 0
Derived from Dockerfile COPY sources (NO hand-maintained allowlist).

Signed-off-by: SZL Holdings <noreply@szlholdings.ai>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

packages/receipt-substrate/src/index.ts CHANGED
@@ -503,6 +503,39 @@ const DIGESTED_SOURCE_QUERY_KEYS = new Set(["code"]);
503
  const SENSITIVE_SOURCE_QUERY_PREFIXES = ["x-amz-", "x-goog-", "x-oss-"];
504
  const TRACKING_SOURCE_QUERY_PREFIXES = ["utm_"];
505
  const TRACKING_SOURCE_QUERY_KEYS = new Set(["fbclid", "gclid", "mc_cid", "mc_eid"]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
 
507
  function cleanOptionalText(value: unknown, maxLength = 256): string | undefined {
508
  if (typeof value !== "string") return undefined;
@@ -641,67 +674,149 @@ function normalizeResearchUsage(input: ResearchUsageInput | undefined): Normaliz
641
  return Object.keys(usage).length > 0 ? usage : undefined;
642
  }
643
 
 
 
 
 
 
 
 
 
 
 
 
644
  function projectNormalizedResearchSource(
645
- input: NormalizedResearchSource,
646
  ): NormalizedResearchSource {
 
 
 
 
 
 
 
 
647
  return {
648
- url: input.url,
649
- domain: input.domain,
650
- ...(input.title_sha256 !== undefined ? { title_sha256: input.title_sha256 } : {}),
651
- ...(input.published_at !== undefined ? { published_at: input.published_at } : {}),
652
- ...(input.last_updated_at !== undefined
653
- ? { last_updated_at: input.last_updated_at }
654
- : {}),
655
  };
656
  }
657
 
658
  function projectNormalizedResearchUsage(
659
- input: NormalizedResearchUsage | undefined,
660
  ): NormalizedResearchUsage | undefined {
661
- if (!input) return undefined;
662
  const projected: NormalizedResearchUsage = {
663
- ...(input.input_tokens !== undefined ? { input_tokens: input.input_tokens } : {}),
664
- ...(input.output_tokens !== undefined ? { output_tokens: input.output_tokens } : {}),
665
- ...(input.total_tokens !== undefined ? { total_tokens: input.total_tokens } : {}),
666
- ...(input.reasoning_tokens !== undefined
667
- ? { reasoning_tokens: input.reasoning_tokens }
668
  : {}),
669
- ...(input.cached_tokens !== undefined ? { cached_tokens: input.cached_tokens } : {}),
670
- ...(input.search_queries !== undefined
671
- ? { search_queries: input.search_queries }
 
 
 
 
 
 
 
 
 
 
 
672
  : {}),
673
  };
674
  return Object.keys(projected).length > 0 ? projected : undefined;
675
  }
676
 
677
  function projectNormalizedProviderEvidence(
678
- input: NormalizedResearchProviderEvidence,
679
  ): NormalizedResearchProviderEvidence {
680
- const usage = projectNormalizedResearchUsage(input.usage);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
681
  return {
682
- schema_version: input.schema_version,
683
- provider: input.provider,
684
- api_surface: input.api_surface,
685
- tool: input.tool,
686
- status: input.status,
687
- query_sha256: input.query_sha256,
688
- policy_sha256: input.policy_sha256,
689
- ...(input.response_id !== undefined ? { response_id: input.response_id } : {}),
690
- ...(input.model !== undefined ? { model: input.model } : {}),
691
- ...(input.http_status !== undefined ? { http_status: input.http_status } : {}),
692
- ...(input.caller_observed_latency_ms !== undefined
693
- ? { caller_observed_latency_ms: input.caller_observed_latency_ms }
694
- : {}),
695
  ...(usage ? { usage } : {}),
696
- ...(input.provider_reported_cost_usd !== undefined
697
- ? { provider_reported_cost_usd: input.provider_reported_cost_usd }
698
- : {}),
699
- sources: input.sources.map(projectNormalizedResearchSource),
700
- source_count: input.source_count,
701
- source_list_sha256: input.source_list_sha256,
702
  };
703
  }
704
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
705
  function normalizeProviderEvidence(input: {
706
  readonly provider: ResearchProvider;
707
  readonly api_surface: NormalizedResearchProviderEvidence["api_surface"];
@@ -805,10 +920,13 @@ export function compareResearchEvidence(input: {
805
  }): ResearchEvidenceComparison {
806
  const querySha256 = cleanSha256(input.query_sha256);
807
  const policySha256 = cleanSha256(input.policy_sha256);
808
- const providers = input.providers
 
 
 
 
809
  .map(projectNormalizedProviderEvidence)
810
  .sort((left, right) => left.provider.localeCompare(right.provider));
811
- const errors: string[] = [];
812
 
813
  if (!SHA256_PATTERN.test(querySha256)) errors.push("expected query_sha256 is not a SHA-256 digest");
814
  if (!SHA256_PATTERN.test(policySha256)) errors.push("expected policy_sha256 is not a SHA-256 digest");
@@ -937,8 +1055,11 @@ export function emitTwoWitnessResearchReceipt(
937
  const payload = {
938
  schema_version: "a11oy.two_witness_research_receipt/v0",
939
  live_adapters_enabled: TWO_WITNESS_LIVE_ADAPTERS_ENABLED,
 
940
  signature_state: "UNSIGNED_LOCAL",
 
941
  external_attestation: false,
 
942
  action_authorized: false,
943
  query_sha256: comparison.query_sha256,
944
  policy_sha256: comparison.policy_sha256,
 
503
  const SENSITIVE_SOURCE_QUERY_PREFIXES = ["x-amz-", "x-goog-", "x-oss-"];
504
  const TRACKING_SOURCE_QUERY_PREFIXES = ["utm_"];
505
  const TRACKING_SOURCE_QUERY_KEYS = new Set(["fbclid", "gclid", "mc_cid", "mc_eid"]);
506
+ const NORMALIZED_PROVIDER_KEYS = new Set([
507
+ "schema_version",
508
+ "provider",
509
+ "api_surface",
510
+ "tool",
511
+ "status",
512
+ "query_sha256",
513
+ "policy_sha256",
514
+ "response_id",
515
+ "model",
516
+ "http_status",
517
+ "caller_observed_latency_ms",
518
+ "usage",
519
+ "provider_reported_cost_usd",
520
+ "sources",
521
+ "source_count",
522
+ "source_list_sha256",
523
+ ]);
524
+ const NORMALIZED_SOURCE_KEYS = new Set([
525
+ "url",
526
+ "domain",
527
+ "title_sha256",
528
+ "published_at",
529
+ "last_updated_at",
530
+ ]);
531
+ const NORMALIZED_USAGE_KEYS = new Set([
532
+ "input_tokens",
533
+ "output_tokens",
534
+ "total_tokens",
535
+ "reasoning_tokens",
536
+ "cached_tokens",
537
+ "search_queries",
538
+ ]);
539
 
540
  function cleanOptionalText(value: unknown, maxLength = 256): string | undefined {
541
  if (typeof value !== "string") return undefined;
 
674
  return Object.keys(usage).length > 0 ? usage : undefined;
675
  }
676
 
677
+ function isRecord(value: unknown): value is Record<string, unknown> {
678
+ return typeof value === "object" && value !== null && !Array.isArray(value);
679
+ }
680
+
681
+ function unexpectedKeys(
682
+ value: Record<string, unknown>,
683
+ allowed: ReadonlySet<string>,
684
+ ): readonly string[] {
685
+ return Object.keys(value).filter((key) => !allowed.has(key)).sort();
686
+ }
687
+
688
  function projectNormalizedResearchSource(
689
+ input: unknown,
690
  ): NormalizedResearchSource {
691
+ const record = isRecord(input) ? input : {};
692
+ const url = cleanSourceUrl(record.url) ?? "";
693
+ const domain = cleanOptionalText(record.domain, 253)?.toLowerCase() ?? "";
694
+ const titleSha256 = record.title_sha256 === undefined
695
+ ? undefined
696
+ : cleanSha256(record.title_sha256);
697
+ const publishedAt = cleanDate(record.published_at);
698
+ const lastUpdatedAt = cleanDate(record.last_updated_at);
699
  return {
700
+ url,
701
+ domain,
702
+ ...(titleSha256 !== undefined ? { title_sha256: titleSha256 } : {}),
703
+ ...(publishedAt !== undefined ? { published_at: publishedAt } : {}),
704
+ ...(lastUpdatedAt !== undefined ? { last_updated_at: lastUpdatedAt } : {}),
 
 
705
  };
706
  }
707
 
708
  function projectNormalizedResearchUsage(
709
+ input: unknown,
710
  ): NormalizedResearchUsage | undefined {
711
+ if (!isRecord(input)) return undefined;
712
  const projected: NormalizedResearchUsage = {
713
+ ...(cleanNonNegativeInteger(input.input_tokens) !== undefined
714
+ ? { input_tokens: cleanNonNegativeInteger(input.input_tokens) }
 
 
 
715
  : {}),
716
+ ...(cleanNonNegativeInteger(input.output_tokens) !== undefined
717
+ ? { output_tokens: cleanNonNegativeInteger(input.output_tokens) }
718
+ : {}),
719
+ ...(cleanNonNegativeInteger(input.total_tokens) !== undefined
720
+ ? { total_tokens: cleanNonNegativeInteger(input.total_tokens) }
721
+ : {}),
722
+ ...(cleanNonNegativeInteger(input.reasoning_tokens) !== undefined
723
+ ? { reasoning_tokens: cleanNonNegativeInteger(input.reasoning_tokens) }
724
+ : {}),
725
+ ...(cleanNonNegativeInteger(input.cached_tokens) !== undefined
726
+ ? { cached_tokens: cleanNonNegativeInteger(input.cached_tokens) }
727
+ : {}),
728
+ ...(cleanNonNegativeInteger(input.search_queries) !== undefined
729
+ ? { search_queries: cleanNonNegativeInteger(input.search_queries) }
730
  : {}),
731
  };
732
  return Object.keys(projected).length > 0 ? projected : undefined;
733
  }
734
 
735
  function projectNormalizedProviderEvidence(
736
+ input: unknown,
737
  ): NormalizedResearchProviderEvidence {
738
+ const record = isRecord(input) ? input : {};
739
+ const provider = record.provider === "openai" || record.provider === "perplexity"
740
+ ? record.provider
741
+ : "invalid" as ResearchProvider;
742
+ const apiSurface = record.api_surface === "openai.responses.web_search"
743
+ || record.api_surface === "perplexity.search"
744
+ ? record.api_surface
745
+ : "invalid" as NormalizedResearchProviderEvidence["api_surface"];
746
+ const tool = record.tool === "web_search" || record.tool === "search"
747
+ ? record.tool
748
+ : "invalid" as NormalizedResearchProviderEvidence["tool"];
749
+ const responseId = cleanOptionalText(record.response_id);
750
+ const model = cleanOptionalText(record.model);
751
+ const httpStatus = cleanHttpStatus(record.http_status);
752
+ const latencyMs = cleanNonNegativeNumber(record.caller_observed_latency_ms);
753
+ const usage = projectNormalizedResearchUsage(record.usage);
754
+ const costUsd = cleanNonNegativeNumber(record.provider_reported_cost_usd);
755
+ const suppliedSources = Array.isArray(record.sources) ? record.sources : [];
756
+ const sources = suppliedSources.map(projectNormalizedResearchSource);
757
  return {
758
+ schema_version: record.schema_version === "a11oy.research_provider_evidence/v0"
759
+ ? record.schema_version
760
+ : "invalid" as NormalizedResearchProviderEvidence["schema_version"],
761
+ provider,
762
+ api_surface: apiSurface,
763
+ tool,
764
+ status: cleanStatus(record.status),
765
+ query_sha256: cleanSha256(record.query_sha256),
766
+ policy_sha256: cleanSha256(record.policy_sha256),
767
+ ...(responseId ? { response_id: responseId } : {}),
768
+ ...(model ? { model } : {}),
769
+ ...(httpStatus !== undefined ? { http_status: httpStatus } : {}),
770
+ ...(latencyMs !== undefined ? { caller_observed_latency_ms: latencyMs } : {}),
771
  ...(usage ? { usage } : {}),
772
+ ...(costUsd !== undefined ? { provider_reported_cost_usd: costUsd } : {}),
773
+ sources,
774
+ source_count: cleanNonNegativeInteger(record.source_count) ?? -1,
775
+ source_list_sha256: cleanSha256(record.source_list_sha256),
 
 
776
  };
777
  }
778
 
779
+ function structuralResearchEvidenceErrors(
780
+ providers: readonly unknown[],
781
+ ): readonly string[] {
782
+ const errors: string[] = [];
783
+ for (const [providerIndex, input] of providers.entries()) {
784
+ if (!isRecord(input)) {
785
+ errors.push(`provider ${providerIndex}: expected an object`);
786
+ continue;
787
+ }
788
+ const providerLabel = input.provider === "openai" || input.provider === "perplexity"
789
+ ? input.provider
790
+ : `provider ${providerIndex}`;
791
+ for (const key of unexpectedKeys(input, NORMALIZED_PROVIDER_KEYS)) {
792
+ errors.push(`${providerLabel}: unexpected provider field ${key}`);
793
+ }
794
+ if (input.usage !== undefined) {
795
+ if (!isRecord(input.usage)) {
796
+ errors.push(`${providerLabel}: usage must be an object`);
797
+ } else {
798
+ for (const key of unexpectedKeys(input.usage, NORMALIZED_USAGE_KEYS)) {
799
+ errors.push(`${providerLabel}: unexpected usage field ${key}`);
800
+ }
801
+ }
802
+ }
803
+ if (!Array.isArray(input.sources)) {
804
+ errors.push(`${providerLabel}: sources must be an array`);
805
+ continue;
806
+ }
807
+ for (const [sourceIndex, source] of input.sources.entries()) {
808
+ if (!isRecord(source)) {
809
+ errors.push(`${providerLabel}: source ${sourceIndex} must be an object`);
810
+ continue;
811
+ }
812
+ for (const key of unexpectedKeys(source, NORMALIZED_SOURCE_KEYS)) {
813
+ errors.push(`${providerLabel}: source ${sourceIndex} unexpected field ${key}`);
814
+ }
815
+ }
816
+ }
817
+ return errors;
818
+ }
819
+
820
  function normalizeProviderEvidence(input: {
821
  readonly provider: ResearchProvider;
822
  readonly api_surface: NormalizedResearchProviderEvidence["api_surface"];
 
920
  }): ResearchEvidenceComparison {
921
  const querySha256 = cleanSha256(input.query_sha256);
922
  const policySha256 = cleanSha256(input.policy_sha256);
923
+ const suppliedProviders = Array.isArray(input.providers) ? input.providers : [];
924
+ const errors = Array.isArray(input.providers)
925
+ ? [...structuralResearchEvidenceErrors(suppliedProviders)]
926
+ : ["providers must be an array"];
927
+ const providers = suppliedProviders
928
  .map(projectNormalizedProviderEvidence)
929
  .sort((left, right) => left.provider.localeCompare(right.provider));
 
930
 
931
  if (!SHA256_PATTERN.test(querySha256)) errors.push("expected query_sha256 is not a SHA-256 digest");
932
  if (!SHA256_PATTERN.test(policySha256)) errors.push("expected policy_sha256 is not a SHA-256 digest");
 
1055
  const payload = {
1056
  schema_version: "a11oy.two_witness_research_receipt/v0",
1057
  live_adapters_enabled: TWO_WITNESS_LIVE_ADAPTERS_ENABLED,
1058
+ evidence_class: "MODELED",
1059
  signature_state: "UNSIGNED_LOCAL",
1060
+ external_attestation_state: "EXTERNAL_ATTESTATION_FALSE",
1061
  external_attestation: false,
1062
+ action_authorization_state: "ACTION_AUTHORIZED_FALSE",
1063
  action_authorized: false,
1064
  query_sha256: comparison.query_sha256,
1065
  policy_sha256: comparison.policy_sha256,
packages/receipt-substrate/src/research_evidence.test.ts CHANGED
@@ -136,7 +136,7 @@ test("vendor-prefixed presigned credentials never enter normalized evidence", ()
136
  assert.equal(openai.sources[0]?.url, "https://research.example/paper?topic=governance");
137
  });
138
 
139
- test("comparison projects provider and source fields through an explicit allowlist", () => {
140
  const base = fixtures.cases.find((candidate) => candidate.name === "matching");
141
  assert.ok(base);
142
  const openai = normalizeOpenAIWebSearchResult(base.openai);
@@ -144,6 +144,10 @@ test("comparison projects provider and source fields through an explicit allowli
144
  const unsafeOpenAI = {
145
  ...openai,
146
  api_key: "must-not-escape",
 
 
 
 
147
  sources: openai.sources.map((source) => ({
148
  ...source,
149
  snippet: "raw snippet must not be receipted",
@@ -154,15 +158,81 @@ test("comparison projects provider and source fields through an explicit allowli
154
  policy_sha256: fixtures.policy_sha256,
155
  providers: [unsafeOpenAI, perplexity],
156
  });
157
- const receipt = emitTwoWitnessResearchReceipt(comparison, {
158
- actor_id: "did:example:projection-test",
159
- });
160
- const serialized = JSON.stringify(receipt.envelope);
161
 
162
  assert.equal(serialized.includes("must-not-escape"), false);
 
163
  assert.equal(serialized.includes("raw snippet must not be receipted"), false);
164
  assert.equal(serialized.includes("\"api_key\""), false);
 
165
  assert.equal(serialized.includes("\"snippet\""), false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  });
167
 
168
  test("live adapters remain disabled and the public label vocabulary excludes a truth claim", () => {
 
136
  assert.equal(openai.sources[0]?.url, "https://research.example/paper?topic=governance");
137
  });
138
 
139
+ test("comparison rejects undeclared provider, usage, and source fields", () => {
140
  const base = fixtures.cases.find((candidate) => candidate.name === "matching");
141
  assert.ok(base);
142
  const openai = normalizeOpenAIWebSearchResult(base.openai);
 
144
  const unsafeOpenAI = {
145
  ...openai,
146
  api_key: "must-not-escape",
147
+ usage: {
148
+ ...(openai.usage ?? {}),
149
+ response_body: "raw usage must not be receipted",
150
+ },
151
  sources: openai.sources.map((source) => ({
152
  ...source,
153
  snippet: "raw snippet must not be receipted",
 
158
  policy_sha256: fixtures.policy_sha256,
159
  providers: [unsafeOpenAI, perplexity],
160
  });
161
+ const serialized = JSON.stringify(comparison);
 
 
 
162
 
163
  assert.equal(serialized.includes("must-not-escape"), false);
164
+ assert.equal(serialized.includes("raw usage must not be receipted"), false);
165
  assert.equal(serialized.includes("raw snippet must not be receipted"), false);
166
  assert.equal(serialized.includes("\"api_key\""), false);
167
+ assert.equal(serialized.includes("\"response_body\""), false);
168
  assert.equal(serialized.includes("\"snippet\""), false);
169
+ assert.equal(comparison.integrity_valid, false);
170
+ assert.ok(
171
+ comparison.integrity_errors.includes("openai: unexpected provider field api_key"),
172
+ );
173
+ assert.ok(
174
+ comparison.integrity_errors.includes("openai: unexpected usage field response_body"),
175
+ );
176
+ assert.ok(
177
+ comparison.integrity_errors.includes("openai: source 0 unexpected field snippet"),
178
+ );
179
+ assert.throws(
180
+ () => emitTwoWitnessResearchReceipt(comparison, {
181
+ actor_id: "did:example:projection-test",
182
+ }),
183
+ /comparison verification failed/,
184
+ );
185
+ });
186
+
187
+ test("direct comparison rebuilds credential-bearing allowed fields before receipt emission", () => {
188
+ const base = fixtures.cases.find((candidate) => candidate.name === "matching");
189
+ assert.ok(base);
190
+ const openai = normalizeOpenAIWebSearchResult(base.openai);
191
+ const perplexity = normalizePerplexitySearchResult(base.perplexity);
192
+ const unsafeOpenAI = {
193
+ ...openai,
194
+ response_id: { api_key: "response-id-secret-must-not-escape" },
195
+ model: { snippet: "model-secret-must-not-escape" },
196
+ sources: openai.sources.map((source, index) => (
197
+ index === 0
198
+ ? {
199
+ ...source,
200
+ url: `${source.url}?X-Amz-Credential=source-secret-must-not-escape`,
201
+ }
202
+ : source
203
+ )),
204
+ } as unknown as NormalizedResearchProviderEvidence;
205
+ const comparison = compareResearchEvidence({
206
+ query_sha256: fixtures.query_sha256,
207
+ policy_sha256: fixtures.policy_sha256,
208
+ providers: [unsafeOpenAI, perplexity],
209
+ });
210
+ const receipt = emitTwoWitnessResearchReceipt(comparison, {
211
+ actor_id: "did:example:allowed-field-negative",
212
+ });
213
+ const serialized = JSON.stringify(receipt.envelope);
214
+ const payload = receipt.envelope.payload as Record<string, unknown>;
215
+
216
+ for (const forbidden of [
217
+ "response-id-secret-must-not-escape",
218
+ "model-secret-must-not-escape",
219
+ "source-secret-must-not-escape",
220
+ ]) {
221
+ assert.equal(serialized.includes(forbidden), false);
222
+ }
223
+ assert.equal(comparison.providers[0]?.response_id, undefined);
224
+ assert.equal(comparison.providers[0]?.model, undefined);
225
+ assert.equal(
226
+ comparison.providers[0]?.sources[0]?.url,
227
+ "https://example.com/research/report",
228
+ );
229
+ assert.equal(comparison.integrity_valid, true);
230
+ assert.equal(payload.evidence_class, "MODELED");
231
+ assert.equal(payload.signature_state, "UNSIGNED_LOCAL");
232
+ assert.equal(payload.external_attestation_state, "EXTERNAL_ATTESTATION_FALSE");
233
+ assert.equal(payload.external_attestation, false);
234
+ assert.equal(payload.action_authorization_state, "ACTION_AUTHORIZED_FALSE");
235
+ assert.equal(payload.action_authorized, false);
236
  });
237
 
238
  test("live adapters remain disabled and the public label vocabulary excludes a truth claim", () => {