Answer NK-WP-0056-T02 owner request: rapp-bounded-executor intake
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

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 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 994874@bnt-lap001
Assistant-Session: 6017c416-d619-47eb-bd1a-f670a02d7d87
This commit is contained in:
tegwick 2026-10-31 14:19:03 +01:00
parent 9c74884641
commit c733e86b0f

View file

@ -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/<image>@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=<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.