diff --git a/SCOPE.md b/SCOPE.md index 834a1d2..d718a3e 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -112,8 +112,8 @@ also `sync_metadata.mapping` and a row in `mappings.db`. | Artifact | Provides | | --- | --- | | PyPI package | Built wheel/sdist; Makefile targets publish to Coulomb Gitea/Forgejo registry | -| Docker + `k8s/railiance/` | GitOps-style deploy on railiance01 (deployment, service, configmap, ExternalSecret) | -| `docs/argocd-gitops.md` | Operator runbook for that deploy | +| Docker image | Built and published by this app repo; production consumes an immutable digest | +| `rapp-issue-core` | Authoritative railiance01 runtime package: manifests, private Service, ExternalSecret references, NetworkPolicy, rollout, rollback, and live evidence | | `docs/package-release.md` | Release notes for packaging | | `registry/` + `CAPABILITY-issue-tracking.yaml` | Reuse-surface / capability federation metadata | | Tests | `tests/` unit coverage for models, CLI, backends, API ingest/query, mapping | @@ -313,11 +313,14 @@ issue_core/ cli/ # Click: issue, project, map, backend, sync, serve api/ # FastAPI: ingest + query (+ auth, schemas) tests/ -docs/ # gitops, nats stub, mapping design, boundary-sync policy -k8s/railiance/ # deploy manifests +docs/ # nats stub, mapping design, boundary-sync policy workplans/ # ADR-001 work items for this repo ``` +Production runtime packaging is intentionally outside this tree in the sibling +`rapp-issue-core` repository. This repo remains authoritative for domain code, +tests, image construction, and Forgejo image publication. + | Concern | Choice | | --- | --- | | Language | Python 3.8+ | @@ -339,7 +342,7 @@ workplans/ # ADR-001 work items for this repo - `docs/boundary-sync-and-status-mapping.md` — dual-lifecycle outward policy (v1) - `docs/intent-work-record-alignment-review.md` — INTENT vs work-record audit - `docs/nats-task-ingestion.md` — NATS design stub -- `docs/argocd-gitops.md` — railiance01 deploy +- `rapp-issue-core` — authoritative railiance01 deployment and live evidence - `AGENT_INTEGRATION.md` — library patterns for tracker ops - `workplans/ISSUE-WP-0004-align-with-work-record-canon.md` — initial framing pivot - `workplans/ISSUE-WP-0005-connector-alignment-implementation.md` — **finished**: mapping + scope gaps diff --git a/docs/argocd-gitops.md b/docs/argocd-gitops.md deleted file mode 100644 index a34e4dc..0000000 --- a/docs/argocd-gitops.md +++ /dev/null @@ -1,168 +0,0 @@ -# ArgoCD GitOps deployment - railiance01 - -This runbook captures the issue-core side of the railiance01 GitOps pilot. -It keeps secrets out of Git and leaves platform-owned bootstrap steps in -railiance-platform. - -## Source layout - -- Workload bundle: `issue-core/k8s/railiance/` -- Image: `forgejo.coulomb.social/coulomb/issue-core:0.2.1` -- Container port and Service port: `8765` -- Cluster Service URL: `http://issue-core.issue-core.svc.cluster.local:8765` -- Tenant Application: `railiance-platform/argocd/applications/issue-core.application.yaml` - -The `Application` should point at this repo's `k8s/railiance` path and use -`CreateNamespace=true` for the `issue-core` namespace. The namespace itself is -therefore intentionally not duplicated in this bundle. - -## Platform gates - -The following pieces are owned by railiance-platform for the live pilot and for -any future cluster replay: - -- ArgoCD repository credentials and the project/app-of-apps convention. -- The `issue-core` ArgoCD `Application`. -- External Secrets Operator and a `ClusterSecretStore` named `openbao`. -- OpenBao entries for the issue-core runtime Secret. - -For the 2026-06-25 live deployment, these gates were satisfied and the -`issue-core` Application reached Synced/Healthy with image `0.2.1`. - -## Secret contract - -Kubernetes Secret name: `issue-core-runtime` - -Current issue-core manifest path: - -```text -platform/workloads/issue-core/issue-core/issue-core-runtime -``` - -Credential custody is owned by railiance-platform/OpenBao. For agents, first -use the non-secret route catalog entry `activity-core-issue-sink` to confirm -the activity-core + issue-core pairing, and never request the value from -ops-warden. - -Required properties: - -- `ISSUE_CORE_API_KEY` - shared ingestion key used by issue-core and - activity-core. -- `GITEA_BACKEND_TOKEN` - token for creating issues in cluster Gitea. - -Never write either value to Git, State Hub, workplans, logs, or chat. Record -only non-secret evidence such as Secret key count, ExternalSecret readiness, -HTTP status codes, and created issue URLs. - -## Build and publish - -Build the checked-out source tree and publish a registry tag that ArgoCD can -pull: - -```bash -docker build -t forgejo.coulomb.social/coulomb/issue-core:0.2.1 . -docker push forgejo.coulomb.social/coulomb/issue-core:0.2.1 -``` - -The Coulomb Gitea package is public-pullable for this image, so the workload -does not use an `imagePullSecret`. - -## Pre-sync validation - -From the issue-core repo: - -```bash -kubectl kustomize k8s/railiance -``` - -The rendered resources should be: - -- `ExternalSecret/issue-core-runtime` -- `ConfigMap/issue-core-backends` -- `Deployment/issue-core` -- `Service/issue-core` - -## Sync verification - -After railiance-platform syncs the tenant `Application`: - -```bash -kubectl get application issue-core -n argocd -kubectl -n issue-core get externalsecret issue-core-runtime -kubectl -n issue-core get secret issue-core-runtime -kubectl -n issue-core get deploy,pod,svc -``` - -Expected non-secret evidence: - -- ArgoCD Application reports `Synced` and `Healthy`. -- `ExternalSecret/issue-core-runtime` reports Ready. -- `Secret/issue-core-runtime` exists with two data keys. -- `Deployment/issue-core` has one available replica. -- `Service/issue-core` exposes port `8765`. - -Health check from inside the cluster: - -```bash -kubectl -n issue-core run issue-core-health --rm -i --restart=Never --image=curlimages/curl:8.8.0 -- http://issue-core:8765/healthz -``` - -## Ingestion smoke - -Run the authenticated smoke from a short-lived Job so the API key is mounted -from the Kubernetes Secret without printing it: - -```bash -kubectl -n issue-core delete job issue-core-smoke --ignore-not-found -kubectl -n issue-core apply -f - <<'YAML' -apiVersion: batch/v1 -kind: Job -metadata: - name: issue-core-smoke -spec: - ttlSecondsAfterFinished: 600 - backoffLimit: 0 - template: - spec: - restartPolicy: Never - containers: - - name: smoke - image: curlimages/curl:8.8.0 - env: - - name: ISSUE_CORE_API_KEY - valueFrom: - secretKeyRef: - name: issue-core-runtime - key: ISSUE_CORE_API_KEY - command: ["/bin/sh", "-ceu"] - args: - - | - curl -fsS -X POST "http://issue-core:8765/issues/" -H "Authorization: Bearer ${ISSUE_CORE_API_KEY}" -H "Content-Type: application/json" --data '{"title":"issue-core railiance01 smoke","description":"GitOps smoke created by the issue-core deployment runbook.","target_repo":"coulomb/markitect-main","priority":"low","labels":["smoke","issue-core"],"source_type":"rule","source_id":"issue-core-gitops-smoke","triggering_event_id":"scheduled","activity_definition_id":"issue-core-gitops-smoke"}' -YAML -kubectl -n issue-core wait --for=condition=complete job/issue-core-smoke --timeout=90s -kubectl -n issue-core logs job/issue-core-smoke -``` - -Acceptance evidence is HTTP 201 plus a response body containing `issue_id`, -`backend: "gitea"`, and an `issue_url` for cluster Gitea. - -Cleanup: - -```bash -kubectl -n issue-core delete job issue-core-smoke -``` - -## Activity-core handoff - -After issue-core is Ready and the shared `ISSUE_CORE_API_KEY` is available to -activity-core from the same approved OpenBao source: - -- Set `ISSUE_CORE_URL=http://issue-core.issue-core.svc.cluster.local:8765`. -- Set `ISSUE_SINK_TYPE=rest`. -- Inject the same `ISSUE_CORE_API_KEY` into the activity-core worker. -- Keep cron-triggered emissions explicit: `triggering_event_id` may be a stable - non-empty scheduler key such as `scheduled`; event-driven emissions should - continue to send the event UUID. - -Verify by running an activity-core emission and confirming that issue-core -returns HTTP 201 and creates a Gitea issue. diff --git a/k8s/railiance/configmap-backends.yaml b/k8s/railiance/configmap-backends.yaml deleted file mode 100644 index 2542797..0000000 --- a/k8s/railiance/configmap-backends.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Non-secret backend structure for issue-core on CoulombCore. -# Default backend = Forgejo task inbox (Gitea-compatible API). Legacy in-cluster -# gitea-http was retired; all coulomb/* repos there are archived (issue create 423). -# Token is injected at startup from GITEA_BACKEND_TOKEN (ExternalSecret) — must be -# a Forgejo API token with issues:create on the default repo. -apiVersion: v1 -kind: ConfigMap -metadata: - name: issue-core-backends - namespace: issue-core - labels: - app.kubernetes.io/name: issue-core - app.kubernetes.io/part-of: railiance-gitops -data: - backends.json: | - { - "forgejo-inbox": { - "type": "gitea", - "base_url": "https://forgejo.coulomb.social", - "owner": "coulomb", - "repo": "the-custodian", - "token": "__FROM_ENV__" - }, - "default": "forgejo-inbox" - } diff --git a/k8s/railiance/deployment.yaml b/k8s/railiance/deployment.yaml deleted file mode 100644 index f5914c3..0000000 --- a/k8s/railiance/deployment.yaml +++ /dev/null @@ -1,72 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: issue-core - namespace: issue-core - labels: - app.kubernetes.io/name: issue-core - app.kubernetes.io/part-of: railiance-gitops - annotations: - argocd.argoproj.io/sync-wave: "1" # after the ExternalSecret (wave 0) -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: issue-core - template: - metadata: - labels: - app.kubernetes.io/name: issue-core - app.kubernetes.io/part-of: railiance-gitops - spec: - # Image is public-pullable from the Gitea registry (per railiance-forge - # docs). Add imagePullSecrets: [{name: gitea-registry}] if it becomes private. - containers: - - name: issue-core - image: forgejo.coulomb.social/coulomb/issue-core:0.2.1 - imagePullPolicy: IfNotPresent - ports: - - name: http - containerPort: 8765 - env: - - name: ISSUE_CORE_API_KEY - valueFrom: - secretKeyRef: - name: issue-core-runtime - key: ISSUE_CORE_API_KEY - - name: GITEA_BACKEND_TOKEN - valueFrom: - secretKeyRef: - name: issue-core-runtime - key: GITEA_BACKEND_TOKEN - - name: BACKENDS_TEMPLATE - valueFrom: - configMapKeyRef: - name: issue-core-backends - key: backends.json - readinessProbe: - httpGet: - path: /healthz - port: http - initialDelaySeconds: 5 - periodSeconds: 10 - livenessProbe: - httpGet: - path: /healthz - port: http - initialDelaySeconds: 10 - periodSeconds: 20 - resources: - requests: - cpu: 50m - memory: 128Mi - limits: - cpu: 500m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: false - runAsNonRoot: true - runAsUser: 10001 - capabilities: - drop: ["ALL"] diff --git a/k8s/railiance/externalsecret.yaml b/k8s/railiance/externalsecret.yaml deleted file mode 100644 index 8806713..0000000 --- a/k8s/railiance/externalsecret.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Runtime secrets for issue-core, materialized from OpenBao by External Secrets -# Operator (cluster default per railiance-platform docs/argocd-gitops.md). -# -# DEPENDENCY: External Secrets Operator is not yet installed on railiance01 and -# the OpenBao path below must be provisioned by railiance-platform. Until then -# this resource will not reconcile and the Deployment stays Pending the Secret. -# -# OpenBao path: platform/workloads/issue-core/issue-core/issue-core-runtime -# properties: ISSUE_CORE_API_KEY, GITEA_BACKEND_TOKEN -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: issue-core-runtime - namespace: issue-core - labels: - app.kubernetes.io/name: issue-core - app.kubernetes.io/part-of: railiance-gitops - annotations: - argocd.argoproj.io/sync-wave: "0" # before the Deployment (wave 1) -spec: - refreshInterval: 1h - secretStoreRef: - # Provisioned by railiance-platform during ESO install; name TBC on bootstrap. - name: openbao - kind: ClusterSecretStore - target: - name: issue-core-runtime - creationPolicy: Owner - data: - - secretKey: ISSUE_CORE_API_KEY - remoteRef: - key: platform/workloads/issue-core/issue-core/issue-core-runtime - property: ISSUE_CORE_API_KEY - - secretKey: GITEA_BACKEND_TOKEN - remoteRef: - key: platform/workloads/issue-core/issue-core/issue-core-runtime - property: GITEA_BACKEND_TOKEN diff --git a/k8s/railiance/kustomization.yaml b/k8s/railiance/kustomization.yaml deleted file mode 100644 index 48dede5..0000000 --- a/k8s/railiance/kustomization.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# issue-core workload manifests, synced by the ArgoCD `issue-core` Application -# (path k8s/railiance, destination namespace issue-core, CreateNamespace=true). -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: issue-core - -resources: - - externalsecret.yaml - - configmap-backends.yaml - - deployment.yaml - - service.yaml diff --git a/k8s/railiance/service.yaml b/k8s/railiance/service.yaml deleted file mode 100644 index e899134..0000000 --- a/k8s/railiance/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# ClusterIP exposing issue-core on 8765 as -# issue-core.issue-core.svc.cluster.local:8765 — the address activity-core's -# ISSUE_CORE_URL points at once its k8s runtime port is corrected (8010 -> 8765). -apiVersion: v1 -kind: Service -metadata: - name: issue-core - namespace: issue-core - labels: - app.kubernetes.io/name: issue-core - app.kubernetes.io/part-of: railiance-gitops -spec: - type: ClusterIP - selector: - app.kubernetes.io/name: issue-core - ports: - - name: http - port: 8765 - targetPort: http diff --git a/workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md b/workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md index 0216086..caa8d74 100644 --- a/workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md +++ b/workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md @@ -4,7 +4,7 @@ type: workplan title: "rapp-issue-core: move the runtime off CoulombCore onto railiance01" domain: infotech repo: issue-core -status: active +status: finished owner: codex lane: yellow topic_slug: issue-core @@ -176,7 +176,7 @@ UV_CACHE_DIR=/tmp/issue-core-rmgr-cache uv run --directory ../repo-manager \ ```task id: ISSUE-WP-0007-T02 -status: progress +status: done priority: high state_hub_task_id: "e0427de0-dfac-4848-ba2d-1421167eb704" ``` @@ -193,7 +193,7 @@ records by hand. ```task id: ISSUE-WP-0007-T03 -status: todo +status: done priority: high state_hub_task_id: "d6e5e2ac-7f42-412f-8143-91531f5155e8" ``` @@ -214,7 +214,7 @@ handoff. Two active sources of deployment truth are not allowed. ```task id: ISSUE-WP-0007-T04 -status: todo +status: done priority: high state_hub_task_id: "21974fbd-4962-4732-b407-c531bb2ebfe6" ``` @@ -240,7 +240,7 @@ That is the condition being retired. ```task id: ISSUE-WP-0007-T05 -status: todo +status: done priority: high state_hub_task_id: "3fdbd9ab-3e3f-4ac0-8763-77278a1cc6e6" ``` @@ -263,7 +263,7 @@ still pointed at `127.0.0.1:18765`. ```task id: ISSUE-WP-0007-T06 -status: todo +status: done priority: medium state_hub_task_id: "668e37dc-8ebe-46cc-9a27-905440b1240c" ``` @@ -291,3 +291,24 @@ Remaining CoulombCore services after this: `core-hub-staging` and `inter-hub`. kubeconfig any more — its `k3s-api` tunnel was removed on 2026-08-19, so inspecting the *current* deployment needs that tunnel restored first. - Reviewed 2026-08-19 in issue-core and promoted from `proposed` to `ready`. + +## Completion evidence — 2026-08-19 + +- Created, registered, validated, and published private repo + `coulomb/rapp-issue-core`; wrapper commit `3003c92`, State Hub workstream + `b4c39759-6073-4558-a70c-2f869a31cfca`. +- Fixed the Forgejo lifecycle identifier contract in issue-core commit + `3523a7d`; published and deployed immutable digest + `sha256:a56c80ccbd1690bc0bcea384165b1967704f0fdbaf1c506ce1082f56190b92cf`. +- Full wrapper evidence passed: health 200, unauthenticated 401, authenticated + create 201 + close 200, bounded dependency 503, recovery 201 + close 200, + ExternalSecret ready with two keys, both NetworkPolicies present, previous + digest rollback health 200, and restored-digest re-verification. +- activity-core commit `213e810` now uses + `http://issue-core.issue-core.svc.cluster.local:8765` directly while keeping + `ISSUE_SINK_TYPE=state-hub`; a controlled worker-side request returned + create 201 and close 200. +- Deleted the legacy activity-core bridge resources, stopped and removed both + port-18765 ops-bridge entries, and confirmed the local listener was gone. +- Retired this repo's duplicate `k8s/railiance/` source and obsolete ArgoCD + runbook after the wrapper was pushed and its evidence retained.