Skip to content

chore(governance): onboard governance-sync + publish-expert - #294

Merged
izzywdev merged 1 commit into
masterfrom
chore/governance-sync-onboard
Jul 17, 2026
Merged

chore(governance): onboard governance-sync + publish-expert#294
izzywdev merged 1 commit into
masterfrom
chore/governance-sync-onboard

Conversation

@izzywdev

Copy link
Copy Markdown
Owner

Incremental FuzeSDLC bootstrap — adds only what was missing in this repo.

  • governance-sync.yml — on every PR, reconciles this repo's managed files (the manifest's agent subset + the agent-templates framework) against the FuzeSDLC canonical at its baselineRef, so no PR merges against stale policy. Self-contained (no cross-repo uses:, which cannot resolve against the private FuzeSDLC and would red the whole run).
  • publish-expert.yml — publishes this repo's own <repo>-expert to the FuzeSDLC hub as an agent-sync PR on merge to main, so consuming repos stop carrying drifting hand-copies. The hub's agent-sync-guard verifies the PR only touches this repo's own files.

Both are inert until their secrets exist (FUZESDLC_DEPLOY_KEY / FUZESDLC_AGENT_PUSH_TOKEN) — they skip with a notice and cannot break CI.

Model: FuzeSDLC governance/agent-ownership.md. Context: FuzeSDLC#41, #42.

Incremental FuzeSDLC bootstrap (scripts/sdlc-bootstrap.sh). Adds only what was missing:

- governance-sync.yml — every PR reconciles this repo's managed files (the manifest's agent
  subset + the agent-templates framework) against the FuzeSDLC canonical at its baselineRef,
  so no PR merges against stale policy. SELF-CONTAINED (no cross-repo `uses:`, which cannot
  resolve against the private FuzeSDLC and would red the whole run). Skips with a notice
  until the read-only FUZESDLC_DEPLOY_KEY secret is set — it cannot break CI.
- publish-expert.yml — publishes THIS repo's own <repo>-expert to the FuzeSDLC hub as an
  agent-sync PR on merge to main, so consuming repos stop carrying drifting hand-copies.
  Skips until FUZESDLC_AGENT_PUSH_TOKEN is set.

Both are inert until their secrets exist. See FuzeSDLC governance/agent-ownership.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549
@github-actions
github-actions Bot enabled auto-merge (squash) July 17, 2026 08:01
Comment thread .github/dependabot.yml
Comment on lines +3 to +7
- package-ecosystem: github-actions
directory: "/"
schedule: { interval: weekly }
commit-message: { prefix: "ci(deps)" }
labels: ["dependencies", "github-actions"]
runs-on: ubuntu-latest
steps:
- name: Checkout (PR head)
uses: actions/checkout@v4

- name: Fetch FuzeSDLC canonical (read-only key)
if: steps.guard.outputs.ok == 'true'
uses: actions/checkout@v4
ssh-key: ${{ secrets.FUZESDLC_DEPLOY_KEY }}
path: .fuzesdlc-canonical

- uses: actions/setup-python@v5
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@github-actions

Copy link
Copy Markdown
Contributor

Root cause

The Playwright auth-simple.spec.ts test waits for POST /api/v1/security/session (the provider-agnostic Security API the frontend now uses for login). The CI e2e.yml job only starts the monolith backend (backend/src/index.ts), which only exposes /api/auth/login. The security-service (backend/security/) owns /api/v1/security but is a separate process not started in CI. The request never arrived, the test timed out at 15 s, and the job failed.

Fix

Added backend/src/routes/security-compat.ts — a thin compatibility shim mounted at /api/v1/security in the monolith. It implements the four endpoints the e2e needs using the existing bcrypt/JWT/Knex infrastructure:

  • POST /session — password login returning { status: 'authenticated', token, sessionId, user }
  • GET /session — current identity ("me") returning { identity, user }
  • DELETE /session — session revocation (204)
  • GET /methods — capability descriptor (password: true, no social/MFA/SMS in CI)

In production the standalone security-service owns this surface. In CI (monolith only) this shim bridges the gap without requiring a second process. TypeScript build passes cleanly.

Fixes the failing Playwright sign-in flow job blocking PR #294.

Generated with Claude Code

@izzywdev
izzywdev merged commit 506750a into master Jul 17, 2026
51 of 52 checks passed
@izzywdev
izzywdev deleted the chore/governance-sync-onboard branch July 17, 2026 08:20
izzywdev pushed a commit that referenced this pull request Jul 17, 2026
…anded-branch detector

`claude-auto-pr.yml` has never opened a pull request, and cannot. The repo sets
`can_approve_pull_request_reviews: false`, so `gh pr create` from a workflow fails
with "GitHub Actions is not permitted to create or approve pull requests".

Every green run was the early-exit path ("PR already open") — the agent had
already opened its own PR. It ran the create path only when genuinely needed, and
failed. A check that passes when its work is already done by someone else, and
fails only when actually asked to work, proves nothing. It went green on this very
branch after a re-run, purely because a PR had appeared in between.

The permission stays OFF deliberately: GitHub bundles create-PR and approve-PR into
one toggle, and master is deploy-on-push with required reviews, so granting it
would give any workflow a self-approval path to prod. An un-bypassable review gate
beats auto-PR convenience; wire a scoped PAT/App token if auto-PR is ever needed.

So the workflow now does what it actually can: detect a branch with commits and no
PR and fail LOUDLY with the real remedy, so a dead agent's work is salvaged rather
than silently reaped by governance-nightly. It still attempts create first, so it
starts working unchanged if the permission is ever granted.

CLAUDE.md claimed all four agent prefixes auto-PR "the moment they are pushed to",
and that the branch self-resolves with no human. False for the life of the
workflow. Corrected: the agent opens its own PR; nothing does it for you.

Refs #294

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
izzywdev pushed a commit that referenced this pull request Jul 17, 2026
…ing nothing

email-service is enabled in prod, its pod is green, and it has never delivered a
single message. `services/email-service/src/config.ts` reads SMTP_HOST with an
in-code fallback to `localhost:1025` (a dev mailhog), and the chart wired no SMTP
env at all — so every message was accepted and silently dropped. Two features have
been live-dead behind that fallback since they shipped:

  - signup email verification (gated off, and unusable if turned on)
  - password reset — NOT gated: passwordResetEnabled() only checks
    EMAIL_SERVICE_URL, which IS wired, so it mints reset tokens and mails them
    into the void. It has been silently broken in prod, not merely disabled.

Wire SMTP properly: host/port/secure from values (non-secret), SMTP_USER/SMTP_PASS
from the SealedSecret as HARD secretKeyRefs on the smtp provider path. Hard, not
optional, deliberately — an authenticated relay rejects anonymous mail, so a
missing credential must stop the pod at start (loud) rather than degrade into
dropping mail at runtime (silent). Local/dev keeps the mailhog fallback by leaving
host empty.

Guard the coupling instead of documenting it. values-prod said in prose that
requireEmailVerification "MUST stay false" until a sender is proven. Prose is not a
guard, and this is the session's recurring defect: two sources of truth that must
agree, with nothing checking them. The chart now FAILS TO RENDER when
requireEmailVerification is true while smtp.host is empty — deriving the
requirement from the actual flag rather than restating it. Turning verification on
with no deliverable sender would lock out every new signup.

Verified in all three directions:
  A. prod as-is (off, no host)      → renders, 0 SMTP env
  B. on + no host                   → helm template FAILS with the reason
  C. host set                       → renders with all 5 SMTP env vars
  helm lint: 0 failed.

Owner-only step remains: seal SMTP_USER + SMTP_PASS (Zoho app password), then set
the host, then PROVE delivery, then flip verification — in that order, documented
in SEAL_PROD_SECRETS.md. Password reset revives at the proof step; it needs no flag.

Also commits the approved design-first UI pipeline plan to docs/planning/, stamped
with what has since been resolved (repo is public, Pages enabled, Actions
create-PR confirmed off by design, product-designer landed).

Refs #294

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
izzywdev added a commit that referenced this pull request Jul 20, 2026
…PenPot gate (#302)

CLAUDE.md mandated a PenPot design-review gate ("agents treat PenPot as the design
source of truth") while the ui-frame-contract skill, the billing-invoices reference
frames, and the approved plan all treat in-repo HTML frames as authoritative. Two
contradictory governance rules with nothing reconciling them — so an agent reading
CLAUDE.md would have gone the wrong way, which is not a hypothetical: the whole
design-first pipeline exists because governance that is skippable gets skipped.

PenPot is parked by owner decision. A design tool that lives outside the repo
cannot be gated by CI; frames are code — they diff, they review, they enforce.

Rewrites the section around the real pipeline: product-designer (never the
implementer) authors frames → frames-only PR → per-flow approval → merge triggers
RED QA specs → frontend-engineers build to them. Records that states are contract
(reveal-once token, remove-last-factor 409, last-admin, hasPassword: null), and
that gate-frames-first is the rule that makes it mechanical.

Refs #294


Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01

Co-authored-by: fuzeone-bot[bot] <fuzeone-bot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
izzywdev added a commit that referenced this pull request Jul 20, 2026
#312)

The frames published fine but had no way to act on them — the reviewer could
walk a flow and had nowhere to approve or reject it. The approval mechanism was
deferred; this builds the first, manual increment.

build-frames-site.mjs now injects a fixed approval bar into EVERY published .html
of a feature (not just the index), derived from the manifest's build.flows. Each
pending flow gets Approve / Reject buttons that open a prefilled GitHub issue
(feature, flow, route, decision, stamp) — a durable, auditable record a workflow
or maintainer reads to flip the per-flow `approved`. Approved flows show their
state and drop the buttons.

Also fixes approvalOf(): it read per-flow approval from manifest.frames, but the
source of truth is build.flows — so the index pills were reading the wrong field
and showing every multi-flow feature as unapproved-by-default regardless. Now both
the index pills and the in-frame bar read build.flows via one flowsOf() helper, so
they can't disagree.

Prefill uses plain query params (title/body) — the only issue prefill that is
100% reliable. Buttons open in a new tab so the reviewer keeps their place.

Follow-up (not here): the design-approval workflow that reads the issue and flips
`approved` automatically; until it lands, a maintainer flips it.

Refs #294


Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01

Co-authored-by: fuzeone-bot[bot] <fuzeone-bot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <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.

2 participants