i-repo 2.11.0 → 2.12.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.
@@ -14,6 +14,8 @@ import { accessSync, constants, readdirSync, statSync } from "node:fs";
14
14
  import { homedir } from "node:os";
15
15
  import { delimiter, isAbsolute, join } from "node:path";
16
16
  import { getConfig } from "../config/store.js";
17
+ import { fingerprintEndpoint } from "../config/endpoint-fingerprint.js";
18
+ import { resolveSourceMachine } from "../config/provenance.js";
17
19
  /** Prefix every plugin executable must carry. */
18
20
  export const PLUGIN_PREFIX = "i-repo-";
19
21
  const isWin = process.platform === "win32";
@@ -246,6 +248,19 @@ export function buildPluginEnv(ctx, opts = {}) {
246
248
  env.IREPO_TIMEOUT = String(timeout);
247
249
  env.IREPO_QUIET = quiet ? "1" : "";
248
250
  env.IREPO_PLUGIN_API = "1";
251
+ // Provenance of the resolved i-Reporter endpoint, computed CLI-side — the CLI
252
+ // is the single source of truth for the fingerprint; plugins must echo these,
253
+ // never fingerprint themselves (would break the frozen rule). Authoritative:
254
+ // scrub any inherited value first (a PATH binary must not be able to spoof its
255
+ // own provenance via env), then set only when the endpoint actually resolves.
256
+ // Absence ⇒ "unknown" (consumers treat it fail-closed, never as a match).
257
+ delete env.IREPO_ENDPOINT_FINGERPRINT;
258
+ delete env.IREPO_ENDPOINT_RESOLVED_FROM;
259
+ const endpointFingerprint = endpoint ? fingerprintEndpoint(String(endpoint)) : "";
260
+ if (endpointFingerprint) {
261
+ env.IREPO_ENDPOINT_FINGERPRINT = endpointFingerprint;
262
+ env.IREPO_ENDPOINT_RESOLVED_FROM = resolveSourceMachine("endpoint", ctx.endpoint);
263
+ }
249
264
  return env;
250
265
  }
251
266
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i-repo",
3
- "version": "2.11.0",
3
+ "version": "2.12.0",
4
4
  "description": "Modern CLI for ConMas i-Reporter - Built for humans and AI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -44,7 +44,7 @@ async function loadBuiltins() {
44
44
  }
45
45
 
46
46
  const PLUGIN = "i-repo-archive";
47
- const VERSION = "0.5.7";
47
+ const VERSION = "0.6.0";
48
48
  const PLUGIN_API = "1";
49
49
  const defaultArchiveRoot = () => join(homedir(), ".i-repo", "archives");
50
50
 
@@ -616,9 +616,11 @@ async function createArchive(options) {
616
616
 
617
617
  // Completion marker written last: its absence marks an incomplete bundle.
618
618
  const receiptPath = join(archivePath, "receipts", "archive.json");
619
+ const provenance = endpointProvenance();
619
620
  await writeJsonFile(receiptPath, {
620
621
  jobId, count: records.length,
621
622
  producedBy: { plugin: PLUGIN, version: VERSION }, // 来歴: stdout だけでなく archive.json にも残す
623
+ ...(provenance ? { provenance } : {}), // 接続来歴も stdout receipt と同一値で残す
622
624
  ...extras,
623
625
  });
624
626
  savedFiles.push(receiptPath);
@@ -898,11 +900,29 @@ async function pullArchiveBundle(options, backend) {
898
900
 
899
901
  // ── receipts (SCHEMA.md §6) ─────────────────────────────────────────────────
900
902
 
903
+ // 接続来歴: CLI(dispatch) が precomputed して env で渡した値を echo するだけ。指紋は
904
+ // 計算しない(CLI が正本=凍結規則の第2実装を作らない。SCHEMA.md §2.5a/§6)。
905
+ // IREPO_ENDPOINT_FINGERPRINT が無い=endpoint 未解決 → provenance を省略(不明=
906
+ // fail-closed; 消費側は空/不在を「一致」と解釈しない契約)。
907
+ function endpointProvenance() {
908
+ const endpointFingerprint = process.env.IREPO_ENDPOINT_FINGERPRINT;
909
+ if (!endpointFingerprint) return undefined;
910
+ return {
911
+ endpoint: process.env.IREPO_ENDPOINT || "",
912
+ endpointFingerprint,
913
+ user: process.env.IREPO_USER || "",
914
+ resolvedFrom: process.env.IREPO_ENDPOINT_RESOLVED_FROM || "",
915
+ };
916
+ }
917
+
901
918
  function emitReceipt(phase, jobId, count, failedCount, verified, extras) {
919
+ const provenance = endpointProvenance();
902
920
  process.stdout.write(JSON.stringify({
903
921
  schemaVersion: "1.0", recordType: "receipt", plugin: PLUGIN,
904
922
  producedBy: { plugin: PLUGIN, version: VERSION },
905
- phase, jobId, count, failedCount, verified, ...extras,
923
+ phase, jobId, count, failedCount, verified,
924
+ ...(provenance ? { provenance } : {}),
925
+ ...extras,
906
926
  }) + "\n");
907
927
  }
908
928