etch-record 0.7.0__tar.gz → 0.8.0__tar.gz

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 (28) hide show
  1. {etch_record-0.7.0 → etch_record-0.8.0}/CHANGELOG.md +32 -0
  2. {etch_record-0.7.0 → etch_record-0.8.0}/PKG-INFO +1 -1
  3. {etch_record-0.7.0 → etch_record-0.8.0}/pyproject.toml +1 -1
  4. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/__init__.py +1 -1
  5. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/cli.py +56 -1
  6. {etch_record-0.7.0 → etch_record-0.8.0}/.github/workflows/release.yml +0 -0
  7. {etch_record-0.7.0 → etch_record-0.8.0}/.gitignore +0 -0
  8. {etch_record-0.7.0 → etch_record-0.8.0}/LICENSE +0 -0
  9. {etch_record-0.7.0 → etch_record-0.8.0}/README.md +0 -0
  10. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/attestation_client.py +0 -0
  11. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/authority_client.py +0 -0
  12. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/config.py +0 -0
  13. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/governance_client.py +0 -0
  14. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/import_client.py +0 -0
  15. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/mcp_client.py +0 -0
  16. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/rate_limit.py +0 -0
  17. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/stop_condition_client.py +0 -0
  18. {etch_record-0.7.0 → etch_record-0.8.0}/src/etch_record/wave1_4567_clients.py +0 -0
  19. {etch_record-0.7.0 → etch_record-0.8.0}/tests/test_attestation_flags.py +0 -0
  20. {etch_record-0.7.0 → etch_record-0.8.0}/tests/test_authority_flags.py +0 -0
  21. {etch_record-0.7.0 → etch_record-0.8.0}/tests/test_cli.py +0 -0
  22. {etch_record-0.7.0 → etch_record-0.8.0}/tests/test_cli_hardening.py +0 -0
  23. {etch_record-0.7.0 → etch_record-0.8.0}/tests/test_governance_flags.py +0 -0
  24. {etch_record-0.7.0 → etch_record-0.8.0}/tests/test_import_flags.py +0 -0
  25. {etch_record-0.7.0 → etch_record-0.8.0}/tests/test_mcp_client.py +0 -0
  26. {etch_record-0.7.0 → etch_record-0.8.0}/tests/test_rate_limit.py +0 -0
  27. {etch_record-0.7.0 → etch_record-0.8.0}/tests/test_stop_condition_flags.py +0 -0
  28. {etch_record-0.7.0 → etch_record-0.8.0}/tests/test_wave1_4567_flags.py +0 -0
@@ -3,6 +3,38 @@
3
3
  All notable changes to `etch-record` (the CLI helper for the Etch signed
4
4
  audit chain).
5
5
 
6
+ ## v0.8.0 — 2026-08-02
7
+
8
+ Wave 4 #15 8-category drift engine. Extends the governance object
9
+ with 3 new optional fields (mission / terminology / context) so the
10
+ server can populate an 8-dimension projection index. Drift detection
11
+ runs offline via `etch-chain-verify` (added server-side).
12
+
13
+ Server-side dependency: etch commit adding the multi-dim projection
14
+ (this release cycle's server change).
15
+
16
+ ### Added
17
+
18
+ - `--mission <string>` — mission statement (e.g. "customer KYC
19
+ compliance decisions"). Hashed server-side.
20
+ - `--terminology <t1,t2,...>` — comma-separated key terms. Set-hashed
21
+ server-side.
22
+ - `--context-file <path>` — JSON object describing operating context.
23
+ Any shape accepted; canonical-json-hashed server-side.
24
+
25
+ Any of the new flags (alone or with legacy governance flags) triggers
26
+ the governance sub-record call and populates the multi-dim index.
27
+
28
+ ### Positioning
29
+
30
+ Wave 4 #15 is the largest single feature in the boundary plan (10
31
+ dev-days). Ships the full OHRP v2.0 8-category surface:
32
+ mission / assumption / confidence / evidence / scope / terminology /
33
+ authority / context. No observability vendor claims this surface.
34
+
35
+ Content angle for marketing: "8 drift dimensions with independent
36
+ comparators, per-decision on-chain evidence, offline verifier."
37
+
6
38
  ## v0.7.0 — 2026-08-02
7
39
 
8
40
  Wave 2 #10. Adds three flags for recording an explicit halt event
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: etch-record
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: CLI helper: sign any event into your Etch audit chain from the command line.
5
5
  Author: Saravanan Jaichandaran
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "etch-record"
7
- version = "0.7.0"
7
+ version = "0.8.0"
8
8
  description = "CLI helper: sign any event into your Etch audit chain from the command line."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """etch-record: CLI helper for signing arbitrary events into your Etch chain."""
2
2
 
3
- __version__ = "0.7.0"
3
+ __version__ = "0.8.0"
@@ -424,6 +424,39 @@ def _maybe_warn_large_arg(name: str, value: str) -> None:
424
424
  ),
425
425
  )
426
426
  # ---------------------------------------------------------------------------
427
+ # Wave 4 #15 (2026-08-02) — 8-category governance schema extension.
428
+ # Adds mission / terminology / context fields. Extraction is server-
429
+ # side; drift detection runs via etch-chain-verify's dimensional
430
+ # check. Any of these flags being set (alone or with the legacy
431
+ # governance fields) triggers the second call and populates the
432
+ # multi-dim projection index.
433
+ # ---------------------------------------------------------------------------
434
+ @click.option(
435
+ "--mission", "mission", type=str, default=None,
436
+ help=(
437
+ "Wave 4 #15 governance: mission statement string (e.g. "
438
+ "'customer KYC compliance decisions'). Hashed server-side "
439
+ "for drift detection."
440
+ ),
441
+ )
442
+ @click.option(
443
+ "--terminology", "terminology_raw", type=str, default=None,
444
+ help=(
445
+ "Wave 4 #15 governance: comma-separated key terms (e.g. "
446
+ "'KYC,PII,customer identity'). Set-hashed server-side."
447
+ ),
448
+ )
449
+ @click.option(
450
+ "--context-file", "context_file",
451
+ type=click.Path(exists=True, dir_okay=False, path_type=Path),
452
+ default=None,
453
+ help=(
454
+ "Wave 4 #15 governance: JSON object describing the operating "
455
+ "context (e.g. {model, prompt_hash, policy_context}). Any "
456
+ "shape accepted; canonical-json-hashed server-side."
457
+ ),
458
+ )
459
+ # ---------------------------------------------------------------------------
427
460
  # Wave 1 #2 (2026-08-01) — bounded authority receipts.
428
461
  # When --authority-privkey-file + --authority-id + --receipt-type are all
429
462
  # set, the CLI adds a THIRD call:
@@ -725,6 +758,9 @@ def main(
725
758
  uncertainty: str | None,
726
759
  uncertainty_file: Path | None,
727
760
  invalidation_file: Path | None,
761
+ mission: str | None,
762
+ terminology_raw: str | None,
763
+ context_file: Path | None,
728
764
  authority_privkey_file: Path | None,
729
765
  authority_id: str | None,
730
766
  authority_scope: str,
@@ -860,6 +896,9 @@ def main(
860
896
  uncertainty=uncertainty,
861
897
  uncertainty_file=uncertainty_file,
862
898
  invalidation_file=invalidation_file,
899
+ mission=mission,
900
+ terminology_raw=terminology_raw,
901
+ context_file=context_file,
863
902
  )
864
903
  if governance is not None:
865
904
  try:
@@ -1060,12 +1099,20 @@ def _assemble_governance_from_flags(
1060
1099
  uncertainty: str | None,
1061
1100
  uncertainty_file: Path | None,
1062
1101
  invalidation_file: Path | None,
1102
+ mission: str | None = None,
1103
+ terminology_raw: str | None = None,
1104
+ context_file: Path | None = None,
1063
1105
  ) -> dict | None:
1064
1106
  """Compose the governance object from CLI flags, or return None if
1065
- none of them are set (signals: skip the second API call)."""
1107
+ none of them are set (signals: skip the second API call).
1108
+
1109
+ Wave 4 #15 additions: `mission` string, `terminology` list,
1110
+ `context` dict. Any of these plus the legacy 5 fields triggers
1111
+ the second call."""
1066
1112
  if not any((
1067
1113
  policy_hash, authority_file, assumptions_file,
1068
1114
  uncertainty, uncertainty_file, invalidation_file,
1115
+ mission, terminology_raw, context_file,
1069
1116
  )):
1070
1117
  return None
1071
1118
 
@@ -1094,6 +1141,14 @@ def _assemble_governance_from_flags(
1094
1141
  gov["invalidation_conditions"] = _read_json_list(
1095
1142
  invalidation_file, "--invalidation-file",
1096
1143
  )
1144
+ if mission:
1145
+ gov["mission"] = mission
1146
+ if terminology_raw:
1147
+ gov["terminology"] = [
1148
+ t.strip() for t in terminology_raw.split(",") if t.strip()
1149
+ ]
1150
+ if context_file is not None:
1151
+ gov["context"] = _read_json_object(context_file, "--context-file")
1097
1152
  return gov
1098
1153
 
1099
1154
 
File without changes
File without changes
File without changes