proof-harness 0.1.0-next.4 → 0.1.0-next.6

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/COMPATIBILITY.md CHANGED
@@ -11,7 +11,7 @@ Consumers must pin an exact prerelease version, for example:
11
11
  ```json
12
12
  {
13
13
  "devDependencies": {
14
- "proof-harness": "0.1.0-next.4"
14
+ "proof-harness": "0.1.0-next.6"
15
15
  }
16
16
  }
17
17
  ```
@@ -27,6 +27,55 @@ versions rather than guessing how to interpret them.
27
27
 
28
28
  ## Prerelease migration notes
29
29
 
30
+ ### 0.1.0-next.6
31
+
32
+ **Removed: the module-descriptor system.** It served the consumer's planner
33
+ (what a module is for, what a buyer must decide, where answers land) and never
34
+ fed verification, so it is now consumer-owned. Gone from the package:
35
+
36
+ - CLI commands `modules` and `modules-check` (and the `modules` step inside
37
+ `build`); the `.proof/module-policy.json` accept-list introduced in
38
+ `next.5` went with the checker.
39
+ - `proof-harness/shared` exports `ModuleMeta`, `ModuleDecision`,
40
+ `ModuleInput`, `ModuleDefault`, `ModuleSeam`, `ScannedModule`,
41
+ `ModulesArtifact`, `MODULE_DESCRIPTOR_SCHEMA_VERSION`, `MODULE_KINDS`,
42
+ `APPLIED_BY`, `ModuleKind`, `AppliedBy`, `isModuleKind`, `isAppliedBy`.
43
+ - The `proof.config.mjs` keys `artifacts.modules`, `policies.module`,
44
+ `roots.modules`, `roots.sharedModules`, and `moduleKinds` (now ignored if
45
+ supplied).
46
+
47
+ Migration: consumers using the system vendor it from
48
+ `proof-harness@0.1.0-next.5` (Apache-2.0) — `cli/engines/scan_module_meta.mjs`,
49
+ `cli/engines/proof_module_check.mjs`, and `src/shared/module-types.ts` plus the
50
+ two vocabularies above — and point their `module.meta.ts` type imports at the
51
+ vendored copy. Consumers that never ran `proof:modules` are unaffected. Trace,
52
+ mission, and health protocol versions are unchanged.
53
+
54
+ ### 0.1.0-next.5
55
+
56
+ No artifact schema or protocol changes. Three behavioral changes:
57
+
58
+ - **`seed.workspace` no longer writes `type`.** The insert carries only
59
+ `name` plus caller-supplied values — the harness never invents a column
60
+ value it wasn't given. A schema whose `workspaces` table has required
61
+ columns without defaults (the conventional template's `type` included)
62
+ must supply them via `seed.workspace(name, { columns: { … } })` or the new
63
+ `workspaceColumns` option on `assert.tenantIsolation`, or add a database
64
+ default.
65
+ - **`createProofServiceClient` refuses non-local targets.** Any
66
+ `NEXT_PUBLIC_SUPABASE_URL` whose parsed hostname is not
67
+ `localhost`/`127.0.0.1`/`[::1]` aborts as `unsafe_database` before a
68
+ client is constructed, because the suite deletes the users and workspaces
69
+ it seeds. CI setups reaching Supabase through a docker-network hostname
70
+ call `allowProofServiceHosts(["<host>"])` in code; there is no environment
71
+ override.
72
+ - **`modules-check` gains an accept-list.** `.proof/module-policy.json`
73
+ (`schemaVersion: 1`, `acceptedUndescribed: [{ module, reason }]`) lets an
74
+ adopting consumer record undescribed required-root modules as visible debt
75
+ instead of turning the check off. Entries that stop applying fail as
76
+ `module_policy_stale`. Absent file = no acceptances; existing consumers
77
+ are unaffected.
78
+
30
79
  ### 0.1.0-next.4
31
80
 
32
81
  No entry-point, artifact schema, or protocol changes. The `mutate` command
@@ -9,9 +9,6 @@ instead; this document is for anyone _consuming_ the template.
9
9
 
10
10
  > **"Manifest" in this document always means the _mission_ manifest**
11
11
  > (`.proof/current-mission.json`) — the file that pins what one PR must prove.
12
- > It is unrelated to a **module descriptor** (`module.meta.ts` →
13
- > `.proof/modules.json`), which describes what a module is for and what a buyer
14
- > must decide before using it. See §3.1 below.
15
12
 
16
13
  - **Version:** 1 (`schemaVersion` in every manifest and artifact)
17
14
  - **Stability:** The shapes in this document are the contract. Additive
@@ -534,7 +531,6 @@ Everything the template produces that the consumer consumes.
534
531
  | Output | Location | Emitted by | Cadence |
535
532
  | --------------------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------- | -------------------------------------- |
536
533
  | Capability map | `.proof/capabilities.json` (gitignored) | `pnpm proof:scan` (via `proof:build` in setup/CI) | Every setup + CI run |
537
- | Module descriptors | `.proof/modules.json` (gitignored) | `pnpm proof:modules` (via `proof:build` in setup/CI) | Every setup + CI run |
538
534
  | Schema + RLS classification | `.proof/schema.json` (gitignored) | `pnpm proof:parse` (via `proof:build` in setup/CI) | Every setup + CI run |
539
535
  | Proof action allowlist | `app/__shared/proof-runtime/action-registry.generated.ts` | `pnpm proof:registry` | When action requirements/probes change |
540
536
  | PR verification status | GitHub check `Proof` | `pnpm proof:check` in `.github/workflows/ci.yml` | Every PR push |
@@ -714,82 +710,16 @@ from another commit or whose `specFile` no longer exists with `stale_trace`.
714
710
 
715
711
  ---
716
712
 
717
- ### 3.1 Module descriptors — what exists, and what must be decided
713
+ ### 3.1 Module descriptors — moved to the consumer
718
714
 
719
- `.proof/modules.json` answers a different question from everything else here.
720
- The trace artifacts say _"this claim was proved"_; this one says _"this is what
721
- exists, and this is what a buyer has to settle before it can be used"_. It is
722
- what a planning agent reads instead of the template's source, which is the point:
723
- without it the planner needs the codebase in its context, and that grows with
724
- every module we write.
725
-
726
- Regenerate it with `pnpm proof:modules`. Unlike `schema.json` it needs **no
727
- Docker, database, or migration aggregate** — it reads the filesystem and
728
- `capabilities.json`, and takes about a second.
729
-
730
- Each entry has a declared half and a derived half:
731
-
732
- ```jsonc
733
- {
734
- "schemaVersion": 1,
735
- "modules": [
736
- {
737
- // Declared in app/__core/<module>/module.meta.ts
738
- "id": "user-auth",
739
- "kind": "core", // core | extension | business | generated
740
- "purpose": "Signs people in and proves who they are — …",
741
- "env": [],
742
- "decisions": [
743
- {
744
- "id": "mfa_enforcement", // snake_case, unique across all modules
745
- "ask": "Must people use a second factor to sign in?",
746
- "because": "Stricter is safer but adds a step for everyone.",
747
- "options": [{ "value": "optional", "means": "…" }],
748
- "applied_by": "config", // config | content | code
749
- "applies": ["app/__core/user-auth/src/config.ts#MFA_POLICY"],
750
- },
751
- ],
752
- "inputs": [
753
- /* values the buyer supplies rather than picks */
754
- ],
755
- "defaults": [
756
- /* what we chose for them, each with a seam */
757
- ],
758
-
759
- // Derived from source — never written by hand
760
- "path": "app/__core/user-auth",
761
- "entities": [], // tables its own migrations create
762
- "requires": ["config", "user-management"],
763
- "uses_shared": ["ui", "db-supabase"],
764
- "actions": [{ "name": "signin", "verb": null, "object": null }],
765
- "proven": { "specs": 1, "mutations": 0 },
766
- },
767
- ],
768
- // Tables no descriptor claims — today, the ones owned by __shared modules.
769
- "unowned_tables": [
770
- {
771
- "table": "audit_logs",
772
- "module": "audit-logging",
773
- "path": "app/__shared/audit-logging",
774
- },
775
- ],
776
- }
777
- ```
778
-
779
- **Two audiences, one file.** A planner reads `purpose`, `decisions`, `inputs`
780
- and `applied_by` — business language, no paths, roughly 80 tokens per decision.
781
- The agent that _applies_ an answer additionally reads `applies`, which names
782
- every place the answer lands, including files in other modules.
783
-
784
- **Every claim is checked.** `pnpm proof:modules:check` fails when a module has
785
- no descriptor, when an id does not match its directory, when a decision has
786
- fewer than two options or a duplicate id, when a declared environment variable
787
- is undocumented or an undeclared one is read, and — the one that matters most in
788
- practice — **when a seam no longer exists**. A moved file fails CI instead of
789
- quietly sending the next agent to the wrong place.
790
-
791
- Circular dependencies in the derived graph are **reported, not failed**, while a
792
- known inversion is being resolved.
715
+ Until `0.1.0-next.5` the package also shipped a module-descriptor system
716
+ (`module.meta.ts` → `.proof/modules.json`, plus the `modules` and
717
+ `modules-check` commands). It served the consumer's *planner* — what a module
718
+ is for, what a buyer must decide, where answers land — and never fed
719
+ verification, so as of `0.1.0-next.6` it is consumer-owned and no longer part
720
+ of this package. The last release carrying it is `proof-harness@0.1.0-next.5`
721
+ (Apache-2.0), whose implementation is the reference for consumers vendoring
722
+ the system into their own repository.
793
723
 
794
724
  ## 4. Failure contract
795
725
 
@@ -941,6 +871,21 @@ operation }` assertion has neither a matching mutation nor a valid entry in
941
871
  `.proof/mutation-policy.json`, pinned to the current spec hash and a passing
942
872
  positive control. A changed/deleted claim, changed spec, missing control, or
943
873
  newly added mutation makes the acceptance stale and fails inventory.
874
+ - **A proof run cannot target a hosted database.** `createProofServiceClient`
875
+ parses `NEXT_PUBLIC_SUPABASE_URL` and hard-aborts as `unsafe_database` on
876
+ any hostname that is not local — matched on the parsed hostname, never by
877
+ substring, so `localhost.example.com` does not pass. The suite deletes the
878
+ auth users and workspaces it seeds; against a hosted project that failure
879
+ is silent and unrecoverable. There is deliberately no environment-variable
880
+ override: a genuinely disposable non-local host (a docker-network CI
881
+ hostname) is allowed in code via `allowProofServiceHosts`, where a reviewer
882
+ sees it. The mutation runner applies the same refusal to its psql target.
883
+ - **The harness never invents a column value it wasn't given.** Anywhere the
884
+ package writes to a consumer-owned table, the values are caller-supplied or
885
+ the column is omitted — tenancy shape is a consumer decision.
886
+ `seed.workspace` writes only `name`; a schema that requires more states it
887
+ via `seed.workspace(name, { columns })` or `workspaceColumns` on
888
+ `assert.tenantIsolation`.
944
889
  - **A mutation that is not demonstrably live cannot judge a proof.** The
945
890
  mutation runner never (re)applies migrations; it starts (or adopts) the
946
891
  shared dev server before the first defect is planted, then reads each
package/README.md CHANGED
@@ -17,7 +17,7 @@ Public prereleases are published under the npm `next` tag. Pin an exact
17
17
  prerelease version while the API is stabilizing:
18
18
 
19
19
  ```sh
20
- pnpm add proof-harness@0.1.0-next.4
20
+ pnpm add proof-harness@0.1.0-next.6
21
21
  ```
22
22
 
23
23
  The package exposes environment-specific entry points:
@@ -32,9 +32,37 @@ See [PROOF_SDK_CONTRACT.md](./PROOF_SDK_CONTRACT.md) for the consumer contract
32
32
  and [COMPATIBILITY.md](./COMPATIBILITY.md) for protocol/schema compatibility
33
33
  and consumer pinning requirements.
34
34
 
35
+ ## Portability map
36
+
37
+ The package has two layers; consumers should know which one they are leaning
38
+ on:
39
+
40
+ - **Assumes nothing about your schema** — trace recording and the assertion
41
+ vocabulary, mission validation, coverage and its ratchet, drift, mutation
42
+ testing, and the CLI. These read your generated schema and config, or take
43
+ what you give them.
44
+ - **Assumes the conventional Supabase/workspace layout** — `seed.*` (a
45
+ `workspaces` table with a `name` column, a `workspace_members` join table,
46
+ and a `public.users` mirror maintained by a `handle_new_user` trigger) and
47
+ `assert.tenantIsolation`, which seeds through those helpers. The seed
48
+ helpers never invent column values: a schema that requires more than the
49
+ helpers are given states it via `seed.workspace(name, { columns })` or
50
+ `workspaceColumns` on `assert.tenantIsolation`.
51
+
52
+ The `/api/proof/*` routes and the `NEXT_PUBLIC_SUPABASE_URL` /
53
+ `SUPABASE_SECRET_KEY` environment names are documented protocol rather than
54
+ template leakage.
55
+
56
+ `createProofServiceClient` refuses every non-local Supabase target
57
+ (`unsafe_database`): the proof suite deletes the auth users and workspaces it
58
+ seeds, so a hosted project must never be reachable. A genuinely disposable
59
+ non-local host — a docker-network hostname in CI — is allowed explicitly in
60
+ code via `allowProofServiceHosts`; there is deliberately no environment
61
+ override.
62
+
35
63
  The package also provides one `proof-harness` executable with `scan`, `parse`,
36
- `registry`, `build`, `verify`, `coverage`, `inventory`, `drift`, `modules`,
37
- `modules-check`, and `mutate` subcommands. Commands read repository paths from
64
+ `registry`, `build`, `verify`, `coverage`, `inventory`, `drift`, and `mutate`
65
+ subcommands. Commands read repository paths from
38
66
  `proof.config.mjs`; without one they use a conventional application layout.
39
67
  Product migration aggregation and explicit mutation definitions remain
40
68
  repository-owned trust inputs rather than package defaults.
package/cli/config.mjs CHANGED
@@ -6,11 +6,15 @@ const DEFAULT_CONFIG = Object.freeze({
6
6
  artifacts: {
7
7
  capabilities: ".proof/capabilities.json",
8
8
  schema: ".proof/schema.json",
9
- modules: ".proof/modules.json",
10
9
  traces: ".proof/traces",
11
10
  drift: ".proof/drift.json",
12
11
  mutations: ".proof/mutations",
13
12
  },
13
+ // The module-descriptor system (module.meta.ts → modules.json and its
14
+ // checker) moved to the consumer template in 0.1.0-next.6: it serves the
15
+ // planner, which is product, not verification. Its former config keys
16
+ // (artifacts.modules, policies.module, roots.modules, roots.sharedModules,
17
+ // moduleKinds) are ignored if a proof.config.mjs still supplies them.
14
18
  mission: {
15
19
  current: ".proof/current-mission.json",
16
20
  directory: ".proof/missions",
@@ -23,8 +27,6 @@ const DEFAULT_CONFIG = Object.freeze({
23
27
  roots: {
24
28
  source: "app",
25
29
  actions: ["app/__core", "app/__business-logic", "app/__extensions"],
26
- modules: ["app/__core", "app/__extensions", "app/__business-logic"],
27
- sharedModules: "app/__shared",
28
30
  proofs: "e2e/proofs",
29
31
  fixtures: "e2e/fixtures",
30
32
  migrations: "supabase/migrations",
@@ -41,13 +43,6 @@ const DEFAULT_CONFIG = Object.freeze({
41
43
  envExample: ".env.local.example",
42
44
  supabaseConfig: "supabase/config.toml",
43
45
  },
44
- moduleKinds: {
45
- required: [
46
- { root: "app/__core", kind: "core" },
47
- { root: "app/__extensions", kind: "extension" },
48
- ],
49
- optional: [{ root: "app/__business-logic", kind: "business" }],
50
- },
51
46
  driftSources: ["app", "package.json"],
52
47
  mutationCatalog: null,
53
48
  });
@@ -65,10 +60,6 @@ function mergeConfig(config = {}) {
65
60
  ...DEFAULT_CONFIG.registryAliases,
66
61
  ...config.registryAliases,
67
62
  },
68
- moduleKinds: {
69
- ...DEFAULT_CONFIG.moduleKinds,
70
- ...config.moduleKinds,
71
- },
72
63
  };
73
64
  }
74
65
 
@@ -15,8 +15,6 @@ const ENGINES = {
15
15
  verify: "proof_verify.mjs",
16
16
  coverage: "proof_coverage.mjs",
17
17
  drift: "proof_drift.mjs",
18
- modules: "scan_module_meta.mjs",
19
- "modules-check": "proof_module_check.mjs",
20
18
  mutate: "proof_mutation_check.mjs",
21
19
  };
22
20
 
@@ -24,8 +22,7 @@ function printHelp() {
24
22
  console.log(`Usage: proof-harness [--config <path>] <command> [flags]
25
23
 
26
24
  Commands:
27
- scan, parse, registry, build, verify, coverage, inventory, drift,
28
- modules, modules-check, mutate
25
+ scan, parse, registry, build, verify, coverage, inventory, drift, mutate
29
26
 
30
27
  Repository paths and the protected mutation catalog are read from
31
28
  proof.config.mjs. Missing config falls back to a conventional application layout.`);
@@ -74,7 +71,6 @@ export async function runCli(argv = process.argv.slice(2)) {
74
71
  ["scan", []],
75
72
  ["parse", []],
76
73
  ["registry", ["--check"]],
77
- ["modules", []],
78
74
  ]) {
79
75
  const status = runEngine(step, stepArgs, config);
80
76
  if (status !== 0) return status;
@@ -25,8 +25,16 @@ declare const seed: {
25
25
  *
26
26
  * Bypasses RLS via the service-role client, so it works even when no user
27
27
  * is authenticated.
28
+ *
29
+ * The insert writes only `name` plus whatever `opts.columns` supplies: the
30
+ * harness never invents a column value it wasn't given, because tenancy
31
+ * shape is a consumer decision. A schema whose `workspaces` table requires
32
+ * more than `name` (a NOT NULL column without a default) states those
33
+ * values here — or via `workspaceColumns` on `assert.tenantIsolation`.
28
34
  */
29
- workspace(name: string): Promise<SeedWorkspace>;
35
+ workspace(name: string, opts?: {
36
+ columns?: Record<string, unknown>;
37
+ }): Promise<SeedWorkspace>;
30
38
  /**
31
39
  * Create an auth user with the given credentials and attach them to the
32
40
  * provided workspace with the given role. Relies on the `handle_new_user`
@@ -1,4 +1,4 @@
1
- import { h as ProofKind, d as AssertionRole, k as ProofVerb, l as RlsClassification, y as PolicyCommand } from './trace-types-DkIzq-l9.js';
1
+ import { d as ProofKind, a as AssertionRole, g as ProofVerb, h as RlsClassification, t as PolicyCommand } from './trace-types-CbMb65OB.js';
2
2
  import { ACTION_CHANGE_KINDS, TABLE_CHANGE_KINDS } from './portable-vocabulary.js';
3
3
 
4
4
  /**
@@ -296,4 +296,4 @@ interface ValidationResult {
296
296
  evidence?: RequirementEvidence[];
297
297
  }
298
298
 
299
- export { type CapabilityRequirement as C, MISSION_MANIFEST_SCHEMA_VERSION as M, type SchemaRequirement as S, type TraceRequirement as T, type ValidationResult as V, type MissionManifest as a, type MissionRequirements as b, type ValidationCategory as c, type ValidationIssue as d };
299
+ export { type CapabilityRequirement as C, MISSION_MANIFEST_SCHEMA_VERSION as M, type SchemaRequirement as S, type TraceRequirement as T, type ValidationCategory as V, type MissionManifest as a, type MissionRequirements as b, type ValidationIssue as c, type ValidationResult as d };
package/dist/node.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { V as ValidationResult } from './mission-types-Dr5rBHYO.js';
2
- import { T as TraceArtifact, a as TraceAssertion } from './trace-types-DkIzq-l9.js';
1
+ import { d as ValidationResult } from './mission-types-bdwBGf7O.js';
2
+ import { j as TraceArtifact, k as TraceAssertion } from './trace-types-CbMb65OB.js';
3
3
  import './portable-vocabulary.js';
4
4
 
5
5
  interface CapabilitiesArtifact {