Skip to content

Phase A — http-capability-gateway↔BoJ contract + policy authoring workflow + example spec#78

Merged
hyperpolymath merged 1 commit into
mainfrom
hcg/phase-a-contract-and-policy-workflow
May 18, 2026
Merged

Phase A — http-capability-gateway↔BoJ contract + policy authoring workflow + example spec#78
hyperpolymath merged 1 commit into
mainfrom
hcg/phase-a-contract-and-policy-workflow

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Phase A — http-capability-gateway tier-2 integration (ADR-0004)

Single-channel work item: standards#91 parent, standards#96 Phase A (the first of the strictly-sequential A–E). Specification-only — no gateway or BoJ HTTP code is changed (plan §Phase A acceptance criterion).

Deliverables (per docs/integration/http-capability-gateway-plan.md §Phase A)

  • A1 docs/integration/http-capability-gateway-boj-contract.md — transport (TCP loopback staging / Unix socket prod, committed to resolve the plan's port/transport indecision risk), forwarded headers, gateway/BoJ trust vocabulary mapping, error semantics, stealth, deployment trust topology (Phase B input), and surface-drift handling (A3 input).
  • A2 docs/integration/http-capability-gateway-policy-authoring.md — where the spec lives (BoJ repo, option 1), who writes it, POLICY_PATH load sequence, hot-reload triggers, and the co-change anti-drift discipline.
  • A3 config/gateway-policy-boj-example.yaml — 27 rules grounded in docs/specification/openapi.yaml cross-checked against elixir/lib/boj_rest/router.ex; conforms to DSL v1 (audit §2); validated (YAML well-formed, regexes compile, all invariants hold, names unique).

Load-bearing finding

BojRest.Router bypasses trust enforcement for loopback callers. The gateway forwards from loopback, so BoJ will accept the gateway's X-Trust-Level verbatim. Inbound X-Trust-Level stripping + back-side network isolation are therefore mandatory security invariants (contract §3), not advisory — tested in Phase C, hardened in Phase B (mTLS).

Honesty notes (not papered over)

  • The plan's "passes PolicyLoader+PolicyValidator" criterion is a manual check against a running gateway; no gateway runs in Phase A. The example is authored to conform exactly to the documented DSL v1 schema and validated structurally; the running-gateway check is a recorded carry-over (authoring-workflow §6), not a code deliverable, and does not block Phase A.
  • Global-fallback exposure semantics flagged inline as a default-deny caveat to confirm in that manual step.
  • .md (not .adoc) retained for the two docs deliberately — the plan normatively prescribes the contract path and the Phase C Trustfile [SEAMS] entry references it verbatim; rationale stated in-document.

Scope discipline

Phase A only. Phases B–E (#97#100) are not started. This PR uses Refs and does not close standards#91/#96 — they are major,requirements-target (joint-close only, on explicit user agreement).

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#96

🤖 Generated with Claude Code

…e policy

Phase A of the http-capability-gateway tier-2 integration (ADR-0004):
specification-only, no gateway/BoJ HTTP code changes.

A1  docs/integration/http-capability-gateway-boj-contract.md
    Transport (TCP loopback staging / Unix socket prod), forwarded headers,
    error semantics, and the load-bearing trust-header invariant: BojRest.Router
    bypasses trust enforcement for loopback callers, so inbound X-Trust-Level
    stripping + back-side network isolation are mandatory, not advisory.

A2  docs/integration/http-capability-gateway-policy-authoring.md
    Where the spec lives (BoJ repo), who writes it, POLICY_PATH load sequence,
    hot-reload triggers, and the co-change anti-drift discipline.

A3  config/gateway-policy-boj-example.yaml
    27 rules grounded in openapi.yaml cross-checked against router.ex; DSL v1
    valid; surface-drift and default-deny caveats recorded inline rather than
    papered over.

.md (not .adoc) retained for the two docs: the integration plan normatively
prescribes the contract path and the Phase C Trustfile [SEAMS] entry will
reference it verbatim; the docs/integration + docs/decisions set is Markdown.

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#96

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hyperpolymath hyperpolymath merged commit b733860 into main May 18, 2026
11 of 12 checks passed
@hyperpolymath hyperpolymath deleted the hcg/phase-a-contract-and-policy-workflow branch May 18, 2026 09:27
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 28 issues detected

Severity Count
🔴 Critical 17
🟠 High 4
🟡 Medium 7

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Stale AI session file -- delete",
    "type": "stale",
    "file": "GEMINI.md",
    "action": "delete",
    "rule_module": "root_hygiene",
    "severity": "medium"
  },
  {
    "reason": "Issue in quality.yml",
    "type": "missing_workflow",
    "file": "quality.yml",
    "action": "create",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Issue in security-policy.yml",
    "type": "missing_workflow",
    "file": "security-policy.yml",
    "action": "create",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/boj-server/boj-server/cartridges/sanctify-mcp/adapter/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/boj-server/boj-server/cartridges/academic-workflow-mcp/adapter/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/boj-server/boj-server/cartridges/fireflag-mcp/adapter/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/boj-server/boj-server/cartridges/ephapax-mcp/adapter/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/boj-server/boj-server/cartridges/bofig-mcp/adapter/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/boj-server/boj-server/cartridges/hesiod-mcp/adapter/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

hyperpolymath added a commit that referenced this pull request Jun 21, 2026
## Summary

Adds `scripts/hcg-spec-coverage-check.sh`: a static, source-only audit
that asserts every HTTP route declared in
`docs/specification/openapi.yaml` is covered by at least one rule in the
HCG live Verb Governance Spec (`config/gateway-policy-boj.yaml`).

Companion / complement to PR #228's `hcg-surface-drift-check.sh`. The
two scripts bracket the contract §8 declared-surface invariant from both
directions:

| Script | Invariant | Catches |
|---|---|---|
| `hcg-surface-drift-check.sh` (#228) | wired (router.ex) ⊆ policy |
policy lag behind wiring |
| `hcg-spec-coverage-check.sh` (this PR) | declared (openapi.yaml) ⊆
policy | policy lag behind the spec |

Contract §8 (`docs/integration/http-capability-gateway-boj-contract.md`)
is explicit: "the Verb Governance Spec governs the **declared** surface
(openapi.yaml), not only the currently-wired subset.
Declared-but-unimplemented routes are still classified in the policy so
that when the gnosis handler grows them they are governed from day one
rather than silently exposed." The live policy header carries the
cross-check statement (*"Surface source:
docs/specification/openapi.yaml, cross-checked against
elixir/lib/boj_rest/router.ex"*); PR #228 made the router half
machine-checkable, this PR makes the openapi half machine-checkable.
Together they make the entire §1.5 re-verification stamp executable.

Without this check the risk is concrete: someone adds a new path to
`openapi.yaml` without a corresponding policy rule. The surface-drift
check does not catch it (the route is not yet wired in `router.ex`). The
day the route is wired, the surface-drift gate fires — but by then the
operator has to either (a) ship the wiring with a default-deny in
production for a route that should be live or (b) hold the wiring PR
until the policy catches up. Catching the gap at spec-edit time avoids
both, with no procedural cost above running the existing CI gate.

### What the script does

1. Extracts `(verb, path-template)` tuples from the `paths:` section of
`docs/specification/openapi.yaml` — path entries at exactly 2-space
indent, HTTP operations (get/post/put/delete/patch/head/options) at
exactly 4-space indent under each path. Other keys at 4-space indent
(parameters/summary/description/tags/...) are metadata, not operations,
and are skipped.
2. Extracts `(verb, path-pattern)` tuples from
`config/gateway-policy-boj.yaml` using the identical extraction block
that `hcg-surface-drift-check.sh` uses, so the two scripts cannot drift
in how they read the policy.
3. For each declared route, concretises `{name}`-style placeholders with
a known probe segment (`probe`, shared with the smoke + surface-drift
scripts so a future regex tightening fails all three in lock-step) and
asserts at least one policy rule covers it: literal equality for
non-regex paths; ERE `grep -E` match against the concrete URL for `^…`
regex paths. The declared verb must be in the policy rule's verb list.
4. Exit `0` on no gap, `1` on gap detected, `64` on bad usage.

### What this PR does NOT do

- Does **not** modify the rollout runbook §1.5 or the contract §8.
Adoption as the §1.5 declared-surface check is a separate, owner-driven
PR; this PR lands the artefact only so the runbook update is a one-line
wiring change. Matches the §228-then-runbook split.
- Does **not** wire the script into CI. Boj-server's CI discipline
(`docs/wikis/CI-and-Required-Checks.adoc` / `.claude/CLAUDE.md`)
requires path-filtered required checks to use the "always-trigger +
changes job" pattern; a CI wiring PR should follow that pattern,
matching the #228#229 split. Out of scope here.
- Does **not** modify the openapi.yaml or the policy. On this branch the
script reports OK against today's surface — every one of the 26 `(verb,
path)` pairs declared in openapi.yaml has a matching rule among the 28
`(verb, path)` rules in the live policy. The 2-rule surplus is the
policy's coverage of routes the openapi.yaml does not declare (notably
`/.well-known/boj-node-pubkey`, which the router wires but the spec does
not yet enumerate); the script intentionally does not penalise that
direction — see the script's `Limitations` header.
- Does **not** pre-empt the §6.4 Trustfile flip (`tier_2_gateway.status`
stays `PENDING`).
- Per single-lane HCG channel discipline (pattern set in
`http-capability-gateway` PRs #10, #11, #12, #14, #22, #26, #30, #38 and
`boj-server` PRs #78, #90, #106, #168, #173, #207, #208, #210, #215,
#222, #224, #226, #228, #229): joint-close is owner-only. **This PR refs
but does not close `standards#100`.**

### Channel state note

This session could not read `hyperpolymath/standards#91` / `#100` (the
session's repository scope is restricted to `http-capability-gateway`
and `boj-server`), so the brief's instructed status comment on
`standards#91` could not be posted. State was reconstructed from the
canonical sources in this repo (ADR-0004, the integration plan, the
audit, the rollout runbook, the live policy, the openapi spec, and the
merged-PR commit history) plus the current `main` of both in-scope
repos. The analysis: Phase A/B/C/D are closed (artefacts merged, runbook
§1.2 and the Phase-D status note in the runbook header confirm); Phase E
(`standards#100`) is the only open phase; all remaining §1 checklist
items are owner-driven (`!OWNER:` placeholders, D-4 rebaseline
`workflow_dispatch`, cerro-torre `.ctp` signing, the §6.4 Trustfile
flip). This PR advances Phase E §1.5 ("Gateway-side prerequisites") by
converting one half of the declared-surface invariant into an executable
artefact, mirroring exactly the script-first split of #228.

## Test plan

- [ ] Run the script on this branch's working tree: `bash
scripts/hcg-spec-coverage-check.sh` — expect exit `0`, "OK: every
openapi-declared route is covered by at least one policy rule." with
`Declared (openapi) routes: 26` and `Policy (verb,path) rules: 28`.
- [ ] Run `bash scripts/hcg-spec-coverage-check.sh -v` — expect the same
exit `0` plus a `Matched:` block listing each of the 26 declared routes
against its policy rule (literal `/health` → literal rule;
`/cartridge/{name}/invoke` → `^/cartridge/[A-Za-z0-9_.-]+/invoke$`
regex; `/grpc/{service}/{method}` → two-segment regex; `/umoja/peers`
matches both `GET` and `POST` rules; etc.).
- [ ] Synthetic gap test: build a temporary openapi.yaml containing a
single declared path with no policy rule and run `OPENAPI_FILE=... bash
scripts/hcg-spec-coverage-check.sh` — expect exit `1` with the route
listed under `GAP:`. (Verified locally on this branch.)
- [ ] Confirm `shellcheck scripts/hcg-spec-coverage-check.sh` produces
only the same `SC1001` info note that
`scripts/hcg-surface-drift-check.sh` produces today (the `\^` escape
inside a `case` pattern is intentional and matches the sibling script's
posture exactly).
- [ ] Confirm SPDX header + Owner copyright match the canonical estate
format (matches `scripts/hcg-surface-drift-check.sh`'s header shape).
- [ ] Verify `scripts/check-shebang-first.sh` is still green with the
new file present.
- [ ] Verify no Hypatia / governance / spdx gates fire on the new script
file.

Refs hyperpolymath/standards#91
Refs hyperpolymath/standards#100

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
_Generated by [Claude
Code](https://claude.ai/code/session_013VLPKSTEMFnPYQdx6rD91b)_

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant