railiance-apps/docs/rapp-bounded-executor-intake.md
tegwick c733e86b0f
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
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 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 994874@bnt-lap001
Assistant-Session: 6017c416-d619-47eb-bd1a-f670a02d7d87
2026-10-31 14:19:03 +01:00

9.8 KiB

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)

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.