Skip to content

馃彮 Add authenticated GitHub ingress and human delivery#699

Description

@minkimcello

Parent: #633

Architecture ancestry: PR #630

Planning base: 0479b3b1e6a3de08fb7d9de515a3efde80e7fe91; implementation base contains the exact accepted C0 and F1 feedback commits recorded before handoff

Stack position: F2; GitHub-facing work may overlap F1/F3鈥揊6, but feedback is based on accepted F1 transport and storage

Readiness: GitHub-facing work is blocked only on C0; provider integration and feedback are blocked until exact accepted C0 and F1 SHAs are recorded; no authentication, authorization, delivery, or permission choice is delegated

Purpose and observable outcome

An authorized Project movement, human answer, or exact-revision Stage 7 decision becomes one authenticated bounded intake, and a duplicate-safe repository_dispatch wakes the same run without allowing ingress or Actions to select a role outcome or transition.

Authoritative behavior

  • One dedicated GitHub App receives webhooks and authenticated form submissions. It verifies webhook signatures, rereads GitHub state, authenticates the human actor, and retains intake keyed by GitHub delivery/submission identity.
  • Admission requires the configured organization-owned Project V2, repository, Project item, status field, and exact allowed option IDs.
  • A human authorizing admission, an answer, merge, change, or abandonment has Project write and repository write-or-higher access.
  • Answers and Stage 7 decisions come from an App-authenticated web form bound to the exact retained suspension/decision subject, never mutable comment text.
  • repository_dispatch carries only retained intake identity. Actions uses OIDC to ask XMD to start, deliver, or resume; ingress and YAML never parse role output or choose a transition.
  • The App permission ceiling is Metadata read, Contents write, Issues write, Pull requests write, Checks read, Commit statuses read, and organization Projects write. Nothing grants Workflows write; .github/workflows/** mutation is refused.

Current state

The branch has explicit local workflow answer and workflow resume, retained pending answers, GitHub issue/PR adapters, ambient host authentication, and the generic packages/web form/server primitives. It has no GitHub App receiver, signature-verification boundary, actor/Project authorization, durable intake record, OIDC-to-provider exchange, or dispatch route. The generic WebForm does not become lifecycle authority.

Affected modules and public contracts

  • Add host-specific GitHub App HTTP routes, intake storage, form delivery, and OIDC exchange under packages/workflow/src/cloudflare/github-app/** beside F1; do not add GitHub detection to shared workflow modules.
  • Reuse packages/web rendering and response primitives only for presentation/typed submission; GitHub subject binding, actor authentication, and durable delivery remain in the factory ingress adapter.
  • Add closed intake and form-subject records named by C0/F6, with credentials and raw webhook payloads excluded from durable results.
  • Add static App manifest/configuration and Actions dispatch payload validation with exact permission ceilings.
  • Add explicit integration tests under packages/workflow/tests/, packages/web/tests/ where generic behavior changes, and scripts/tests/ for manifest/workflow structure.
  • Update architecture.md, the factory/workflow specifications, public exports, and construct/test inventories in the same feedback commit wherever ingress makes the C0 contract concrete.

Ordered implementation plan

  1. Implement fail-closed GitHub App configuration and webhook signature verification before parsing or routing an event.
  2. Reread issue, repository, Project item/field/option, installation, and actor permissions completely; partial pagination or inaccessible data is unavailability, never absence or denial inferred from missing data.
  3. Normalize one bounded admission/resume intake and retain it under delivery identity in F1 storage before dispatch.
  4. Implement the authenticated answer/Stage 7 form, with one opaque subject that binds the exact run and pending suspension or { headSha, baseSha } decision request.
  5. Exchange Actions OIDC for the exact provider session and deliver only the retained intake identity to XMD's existing start/answer/resume surfaces.
  6. Implement short-lived installation-token minting for downstream F3/F4/L10 effects without persisting or exposing the token.
  7. Add static ceiling checks and duplicate/interruption reconciliation for webhook, form, and dispatch boundaries.

Failure, cancellation, teardown, and replay

Invalid signature, unknown installation, unconfigured repository/Project/field/option, under-authorized actor, stale subject, incomplete reread, duplicate incompatible submission, invalid OIDC, and oversized payload refuse before a workflow session or credential-bearing operation opens. Failure to send or receive dispatch does not change lifecycle authority; a later wakeup delivers the same retained intake. Cancellation closes HTTP/provider resources and records no invented delivery. Completed replay does not revalidate a human or resend a dispatch after the accepted intake/result is retained.

Frozen evidence matrix

  • Valid Project admission retains one intake and wakes the stable run; duplicate delivery adopts the same intake.
  • Invalid signature and every configured-ceiling violation fail before storage, session, token minting, or dispatch.
  • Project and repository permission checks distinguish complete authorization from incomplete/unavailable reads.
  • Comment text cannot admit, answer, merge, change, abandon, or resume anything.
  • A form submission for a stale or different suspension/revision is refused without consuming the active request.
  • Dispatch payload contains only intake identity and no stage, outcome, answer, credential, or transition choice.
  • Dispatch loss/retry and interruption around intake publication produce one compatible delivery.
  • The manifest grants exactly the settled permissions and the host refuses .github/workflows/**, other repositories/Projects/fields/options/branches/targets, force, and under-authorized actors.

Focused feedback evidence

Add explicit tests such as packages/workflow/tests/github-app-ingress.test.ts, packages/workflow/tests/github-app-authorization.test.ts, packages/workflow/tests/github-app-delivery.test.ts, and scripts/tests/software-factory-permissions.test.ts; add a packages/web/tests/ file only if the generic web contract changes. Run the exact files and deno task test --changed. Commit immediately when they pass and report the exact F2 SHA and commands.

Delivery verification

Run deno task lint, deno task check, and deno task check:jsr for public package changes. Workflow or manifest changes also run their explicit scripts/tests/ regression. CI owns exhaustive runtime suites unless shared HTTP/test setup changes.

Exclusions

No lifecycle controller, role-output parser, Project transition, comment mutation, PR readiness, merge, abandonment, PAT, ambient GITHUB_TOKEN mutation, App administration permission, or production secret committed to the repository.

Risks and recovery

GitHub permission names and webhook payloads are external contracts; implementation follows official GitHub App, webhook, Project V2, and Actions OIDC documentation and preserves normalized internal records. If F1's accepted transport must change structurally, return to F1/C0 and restack rather than adding a second intake path.

Handoff

Record exact accepted C0 and F1 SHAs before implementation. Preserve GitHub-facing work already prepared in parallel only if it conforms to those heads. Return one F2 feedback commit with the frozen authorization/delivery evidence; the foundation integration branch merges it after F1, F3, F4, F5, and F6.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions