From c733e86b0fac4802445484233d962181eb57950c Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 31 Oct 2026 14:19:03 +0100 Subject: [PATCH] Answer NK-WP-0056-T02 owner request: rapp-bounded-executor intake Owner answer for who creates the rapp-bounded-executor repository and which Railiance rapp conventions apply. Proposal only. Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 994874@bnt-lap001 Assistant-Session: 6017c416-d619-47eb-bd1a-f670a02d7d87 --- docs/rapp-bounded-executor-intake.md | 151 +++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 docs/rapp-bounded-executor-intake.md diff --git a/docs/rapp-bounded-executor-intake.md b/docs/rapp-bounded-executor-intake.md new file mode 100644 index 0000000..fffef84 --- /dev/null +++ b/docs/rapp-bounded-executor-intake.md @@ -0,0 +1,151 @@ +# rapp-bounded-executor intake (owner answer to NK-WP-0056-T02) + +Status: owner answer from `railiance-apps`, 2026-10-31. Proposal only. Creating +the repository, its Forgejo remote and any live deploy remain founder decisions. + +Request: `net-kingdom/docs/proposals/2026-10-31-nk56-t02-owner-requests.md` +(section "railiance-apps"), hub message `41dbcc41`. Founder decision hub +`6d1adce9`: NetKingdom writes a bounded executor runtime (standard +`net-kingdom/canon/standards/bounded-execution-admission_v0.1.md`); a new +`rapp-*` package deploys it in namespace `sso` with ServiceAccount +`nk-bind-executor`. + +## Short answer + +1. **`railiance-apps` does not create or own the repository.** Under ADR-0015 + and the Railiance family contract, a `rapp-*` is its own repository. This + repository (S5) owns shared app-release lessons and the apps it still hosts + (Path C); it is not the factory for rapp repos. +2. **Who creates it:** the founder, by admitting the creation. The tool is + `repo-manager` (`rmgr rapp wrap`), run from a workstation checkout with + `--ownership-repo net-kingdom`. `wrap` writes local files only. Creating + the Forgejo remote (`coulomb/rapp-bounded-executor`) is a separate + founder-run step. Every existing NetKingdom rapp was bootstrapped this way + (for example `rapp-user-engine`, first commit 2026-08-18, "bootstrap managed + package from NetKingdom apply home"). NetKingdom's agent may run `rmgr rapp + wrap` locally once the founder says the repo should exist. +3. **The image is not built by the rapp.** Correction to the request wording + ("rapp-bounded-executor builds the image"). The fleet rule is that the + **app repo** builds and publishes the image digest + (`.forgejo/workflows/image.yaml`), and the rapp **pins** that digest. + Here the app repo is `net-kingdom`, unless the executor gets its own source + repository (see founder item F2). +4. **Deploy path:** `kubectl` server-side apply of digest-pinned manifests + through the rapp's Makefile (`render`, `server-dry-run`, `deploy`, + `verify-live`, `rollback`). There is no ArgoCD or other GitOps controller + in this estate. Helm is optional; the default for a new first-party rapp is + `manifest-managed-platform-service`. Live apply is founder-run. + +## Conventions that apply (with sources) + +| Topic | Convention | Source | +| --- | --- | --- | +| What a rapp is | One Railiance-managed workload; packaging, not ownership | `railiance-master/docs/repository-axes.md`, ADR-0015 | +| Declaration | `declarations/rapp.yaml`, validated against the schema; there is no `register-rapp` command | `railiance-master/schemas/rapp.schema.json`, `railiance-master/docs/adr/ADR-0007-rapp-declaration-contract.md` | +| Repo baseline | `.repo-classification.yaml`, README, INTENT, SCOPE, AGENTS, CLAUDE, LICENSE, Makefile, `declarations/rapp.yaml`, `workplans/`, `workplans/archived/` | `railiance-master/docs/repo-family-bootstrap-contract.md`; `repo-manager/docs/RailianceAppDeploymentGuide.md` section 6 | +| Greenfield path | `rmgr rapp wrap` → human review → CI digest → `rmgr rapp pin-image` → `rmgr rapp place` → operator deploy | Deployment Guide section 0 | +| Ownership split | Code, tests, Containerfile, image build: app repo. Manifests, ServiceAccount, NetworkPolicy, Makefile, smoke, digest pin: rapp. Secret values: OpenBao via platform. | Deployment Guide section 5 | +| Image | Forge registry `forgejo.coulomb.social/coulomb/@sha256:...`; never a tag; check pull with `railiance-apps/tools/check-oci-image.sh` | Deployment Guide sections 0, 9.4; `docs/s5-app-onboarding-checklist.md` | +| Reef binding | `bound_reefs: []` at `declared`; add `reef-railiance` binding in `reef-railiance/bindings/rapps.yaml` only with an explicit substrate decision | Deployment Guide 10.2; `reef-railiance/bindings/rapps.yaml` notes | +| Readiness | `draft` → `declared` → `deployed`/`verified` only with evidence | Deployment Guide section 6 table | +| Exposure | Omit (private). The executor has no Ingress. | Deployment Guide section 4 | +| Closest model | `rapp-user-engine` (manifest-managed, digest pin, `make verify-live`, `make rollback DIGEST=`) | `~/rapp-user-engine` | + +## Proposed declaration values + +| Field | Proposed value | Why | +| --- | --- | --- | +| `rapp_id` / `repo` | `rapp-bounded-executor` | working name from the request | +| `workload_identity.name` | `bounded-executor` (or `nk-bind-executor`) | must not carry `rapp-` | +| `ownership_repo` | `net-kingdom` | executor runtime is written there | +| `package_type` | `manifest-managed-platform-service` | no existing chart | +| `primary_rail` | `rail-kubernetes` | Job semantics; no scale-to-zero need | +| `bound_reefs` | `[]` until placement is admitted | | +| `data_classification` | `confidential` (consider `restricted`) | it handles directory credentials | +| `criticality` | `high` | it writes identity credentials | +| `runtime_dependencies` | `kubernetes-api`, `forgejo-oci-registry`, `openbao`, `approval-engine`, `lldap` | from the T02 request | +| `secret_references` | the OpenBao paths the secrets-engine answer grants (paths only) | | +| exposure | omitted | | + +## Workload shape: Job, not Deployment + +The standard says one admission is consumed once, before the first step. A +`Job` per admission (`backoffLimit: 0`, `activeDeadlineSeconds` equal to or +shorter than the admission window, `ttlSecondsAfterFinished`) matches that. +A long-running Deployment would hold OpenBao and directory reach with no +admission in hand. Proposed: the rapp ships a Job template and a founder-run +`make run ADMISSION_ID=` that renders the Job with the pinned digest and the +admission id and applies it. No CronJob. + +## Namespace `sso` implications + +- The `sso` Namespace object, and its namespace-wide NetworkPolicy + (`net-kingdom/sso-mfa/k8s/network-policies/netpol-sso.yaml`), currently live + in `net-kingdom`'s migration apply home. The rapp must **not** redeclare the + Namespace. It applies only its own objects in `sso`. +- The rapp ships its own pod-scoped NetworkPolicy: egress to the OpenBao + service, LLDAP, approval-engine and DNS only; no ingress. +- `sso` already hosts KeyCape, LLDAP and Authelia. An executor pod there shares + their namespace. It needs its own Pod Security settings (non-root, read-only + root filesystem, no privilege escalation, dropped capabilities) and + `automountServiceAccountToken` only if the Kubernetes Role below needs it. +- A separate namespace would isolate it more. The founder chose `sso`; record + that choice in the rapp's runtime contract. + +## ServiceAccount and RBAC ownership + +| Object | Owner | Note | +| --- | --- | --- | +| `ServiceAccount nk-bind-executor` (in `sso`) | rapp | per the ownership split | +| `Role` / `RoleBinding` in `sso` (the Kubernetes part of the ceiling) | rapp applies it; **content is set by `net-kingdom`** | the ceiling is NetKingdom canon (BEA standard). The rapp must not widen it. Default: no Kubernetes permissions at all unless a pinned step needs them. | +| OpenBao Kubernetes-auth role bound to `sso/nk-bind-executor` (15-minute TTL) and its policy | `railiance-platform` / `secrets-engine` | answer pending from secrets-engine | +| LLDAP directory account for the executor | NetKingdom / secrets-engine lane | pending | +| Approval consume scope for `service:nk-bind-executor` | approval-engine | pending | +| PDP gate (later) | access-engine | pending | + +## Proposed skeleton (not created) + +```text +rapp-bounded-executor/ + .repo-classification.yaml + README.md INTENT.md SCOPE.md AGENTS.md CLAUDE.md LICENSE + Makefile # check, render, server-dry-run, run ADMISSION_ID=, verify-live, rollback DIGEST= + declarations/rapp.yaml + manifests/ + serviceaccount.yaml # nk-bind-executor + role.yaml # ceiling from net-kingdom; empty by default + networkpolicy.yaml # pod-scoped egress allowlist + job.template.yaml # digest placeholder, admission id parameter + docs/runtime-contract.md # identity table, namespace sso decision, smoke, rollback + docs/platform-handoffs.md # OpenBao role, LLDAP account, approval scope + tools/render.py tools/verify_live.sh + tests/ # render tests, no cluster + workplans/ workplans/archived/ +``` + +And in `net-kingdom` (app repo): `Containerfile` for the executor and +`.forgejo/workflows/image.yaml` (fleet workflow) that publishes +`forgejo.coulomb.social/coulomb/bounded-executor@sha256:...`. + +## Checklist + +1. [ ] Founder: decide the repo should exist (F1) and where the executor source lives (F2). +2. [ ] Founder or NetKingdom agent: `rmgr rapp wrap --path ../rapp-bounded-executor --app bounded-executor --ownership-repo net-kingdom` (local files only). +3. [ ] Founder: create the Forgejo remote `coulomb/rapp-bounded-executor` and push. +4. [ ] NetKingdom: Containerfile and fleet `image.yaml` in the app repo; CI prints a digest. +5. [ ] `rmgr rapp pin-image --digest sha256:...`; `rmgr rapp validate --family-root ..`. +6. [ ] Rapp: ServiceAccount, Role (ceiling from NetKingdom), NetworkPolicy, Job template, Makefile, runtime contract. +7. [ ] Platform owners: OpenBao role and policy, LLDAP account, approval consume scope. +8. [ ] `make server-dry-run` against the cluster (read-only); `check-oci-image.sh` pull check. +9. [ ] Founder: `rmgr rapp place --reef reef-railiance` and a reef binding when the pilot is admitted. +10. [ ] Founder-run first `make run ADMISSION_ID=...` for the T06 pilot; evidence into the rapp. + +## Items for the founder + +- **F1** Admit creation of `rapp-bounded-executor` (local wrap plus Forgejo remote). +- **F2** Executor source home: inside `net-kingdom` (current decision) or a + separate app repo. If it stays in `net-kingdom`, that repo gains a + Containerfile and an image workflow. That is the fleet pattern, but it is new + for a canon repo. +- **F3** Job (recommended) or Deployment. +- **F4** Confirm `sso` over a dedicated namespace, accepting co-tenancy with KeyCape, LLDAP and Authelia.