Skip to content

Story (D): full-file on:/permissions drift guard in compliance-audit [#604] #607

Closed

Description

@don-petry

Part of the shim-identity epic #604 — Story D-audit (full-file guard in compliance-audit).

The compliance audit is field-allowlist, not full-file, so a trimmed on: block passes. check_dev_lead_stub() validates channel pin + agent_ref + no per-stub concurrency: + statuses: read but never on:; the RING branch of check_centralized_workflow_stubs() validates pin only.

Changes (petry-projects/.github)

  • Add a tier-normalized full-file identity check: for each enrolled shim, re-derive the expected stub = canonical standards/workflows/<name>.yml repinned to the target repo's ring tier (reuse deploy-standard-workflows.sh repin logic / ring_canonical_ref, mirroring how template_stub_drift.sh emits-and-compares), then compare against the repo's deployed file. Any diff beyond the tier channel pin → finding.
  • At minimum, guard the on: trigger surface, permissions: block, and absence of per-stub concurrency: for dev-lead and all RING shims (fold into the full-file check or add explicit sub-checks).
  • Tests in the compliance-audit suite: trimmed trigger, added/removed permission, injected concurrency → each flagged; a correctly-tiered stub → clean.

Acceptance

  • A dev-lead.yml (or any RING shim) with a trimmed on: block is flagged by the weekly audit.
  • A stub that differs from the canonical template only by its correct tier channel pin is not flagged.

Activity

  1. don-petry commented on Jul 13, 2026

    @don-petry
    ContributorAuthor

    Dev-Lead Implementation Plan

    Issue: #607 — Story (D): full-file on:/permissions drift guard in compliance-audit [#604]

    Scope

    Add a tier-normalized surface-drift guard to compliance-audit.sh that flags a dev-lead / RING caller stub whose on: triggers, permissions: grants, or (per-stub) concurrency: block have drifted from the canonical standards/workflows/<name>.yml, while never flagging a stub that differs only by its correct tier channel pin.

    Design notes

    • The three guarded surfaces (on:, permissions:, concurrency:) carry no channel pin — the tier pin lives only on the jobs.<id>.uses / agent_ref lines (already guarded by check_centralized_workflow_stubs / check_dev_lead_stub). So the surface comparison is tier-invariant by construction: a stub differing only by its correct tier pin has identical surfaces → not flagged (AC2). This is the "explicit sub-checks" branch Story (D): full-file on:/permissions drift guard in compliance-audit [#604] #607 authorizes, chosen over a full-file byte guard because agent-shield / feature-ideation document legitimate per-repo with: liberties (and feature-ideation a per-repo cron) that a byte guard would false-positive on.
    • feature-ideation's legit per-repo cron retune is tolerated by normalizing - cron: values before comparison; a trimmed trigger still drifts.
    • To avoid duplicate findings, dev-lead's existing dedicated permissions (statuses: read) and concurrency checks in check_dev_lead_stub stay as-is; the new check owns dev-lead's previously-unguarded on: surface plus all three surfaces for the 8 RING shims (whose permissions:/concurrency: were entirely unguarded).

    Implementation Checklist

    • Add pure helpers to scripts/compliance-audit.sh: stub_extract_blocks, stub_normalize_surface, stub_surface_drift
    • Add check_stub_surface_drift(repo) (reads canonical from standards/workflows/, deployed via gh API) + STANDARDS_WF_DIR
    • Wire check_stub_surface_drift "$repo" into the per-repo driver loop

    Tests to Write

    • test/scripts/compliance-audit/stub-surface-drift.bats exercising the real pure helpers:
      • trimmed trigger (removed on: event / narrowed types) → flagged
      • added permission → flagged; removed permission → flagged
      • injected per-stub concurrency: → flagged
      • correctly-tiered stub (differs only by tier channel pin) → clean
      • feature-ideation cron retune → clean; canonical concurrency: retained → clean

    Test Command

    node_modules/.bin/bats test/scripts/compliance-audit/ (CI: bats test/scripts/compliance-audit/)

  2. don-petry commented on Jul 13, 2026

    @don-petry
    ContributorAuthor

    ✅ Issue #607 — full-file on:/permissions drift guard in compliance-audit

    Implemented the tier-normalized surface-drift guard for the centralized caller stubs (dev-lead + all RING shims). Chose the explicit sub-checks branch of the two authorized options: guard the three tier-invariant surfaces (on:, permissions:, concurrency:) rather than a full-file byte guard — a byte guard would false-positive on the documented per-repo with: liberties (agent-shield, feature-ideation) and feature-ideation's documented per-repo cron retune. Because those three surfaces carry no channel pin, the comparison is tier-invariant by construction, which satisfies AC2 automatically.

    Changes

    • scripts/compliance-audit.sh
      • STANDARDS_WF_DIR — points the guard at the on-disk canonical templates in standards/workflows/.
      • Three pure, unit-tested helpers (org standard "decision logic lives in a pure, tested script"):
        • stub_extract_blocks <content> <key> — awk indentation extractor; captures every block for a key at any depth (so dev-lead's top-level permissions: {} + job-level permissions: are both compared), never treats a # concurrency: comment as the key.
        • stub_normalize_surface — strips comments/blank lines and collapses schedule cron: values (so a legitimate per-repo cron retune is not flagged).
        • stub_surface_drift <canonical> <deployed> <key> — success-means-drift (returns 0 on drift, 1 on clean).
      • check_stub_surface_drift <repo> — for each enrolled shim, re-derives the canonical surface and compares against the deployed stub via the contents API. Skips .github (source of truth) and .github-private (runs inline). dev-lead's permissions/concurrency already have dedicated higher-signal checks in check_dev_lead_stub(), so this check owns dev-lead's previously-unguarded on: only, plus all three surfaces for the 8 RING shims. on:/permissions: drift → error; concurrency: → warning. Shim list is in lockstep with RING_REUSABLES in lib/ring-pins.sh.
      • Wired into the driver loop after check_dev_lead_stub.
    • test/scripts/compliance-audit/stub-surface-drift.bats (new, 16 tests) — AC1 (trimmed trigger / narrowed types / dropped discussion → flagged), AC2 (ring1-repinned stub clean on every surface), permissions add/remove flagged, dev-lead statuses: read removal flagged, concurrency injection flagged, feature-ideation canonical concurrency retained clean / changed flagged, cron retune NOT flagged, plus stub_extract_blocks multi-block / absent-key / comment-not-key coverage.

    Acceptance

    • AC1 — a dev-lead.yml (or any RING shim) with a trimmed on: block is flagged ✔ (tests 118–120)
    • AC2 — a stub differing from canonical only by its correct tier channel pin is not flagged ✔ (tests 115–117)

    Verification

    • bats test/scripts/compliance-audit/ → 130 / 130 pass (16 new)
    • shellcheck --severity=warning -x scripts/compliance-audit.sh → clean
    • bash .dev-lead/scripts/dev-lead-lint.sh → all checks passed

    No commit/push/PR performed — leaving git operations to CI.

  3. added a commit that references this issue on Jul 13, 2026
  4. added a commit that references this issue on Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    dev-leadFor dev-lead agent pickup

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions