decomposer: fix validation failure for Migrate the kab_ingestion domain models, ports, GitHub SCM connector, and SharePoint CMS connector into the repository's app/ package.; Wire the migrated ingestion components into the agent application entry point, card, settings, triggers, governance, publication, and validation layers.; Populate every remaining placeholder file with working application, package, test, dependency, and Kubernetes content.; Verify the migrated agent and completed repository end to end.
Some checks failed
quality-gates / verify (push) Failing after 7s

This commit is contained in:
2026-09-01 14:37:28 +00:00
parent 8e32dbdadb
commit 5aba7b6c9d
5 changed files with 125 additions and 11 deletions

View File

@@ -0,0 +1,35 @@
name: quality-gates
on:
push:
branches:
- '**'
pull_request:
branches:
- '**'
jobs:
verify:
runs-on: ubuntu-latest
steps:
- name: Check out source
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: pip
- name: Install project and pinned quality tools
shell: bash
run: |
set -euo pipefail
python -m pip install --upgrade pip
if [[ -f requirements.txt ]]; then python -m pip install -r requirements.txt; fi
if [[ -f requirements-dev.txt ]]; then python -m pip install -r requirements-dev.txt; fi
python -m pip install ruff==0.6.9 mypy==1.11.2 pytest==8.3.3
- name: Lint
run: python -m ruff check .
- name: Type check
run: python -m mypy app
- name: Test
run: python -m pytest -q

20
docs/operator-runbook.md Normal file
View File

@@ -0,0 +1,20 @@
# Content Ingestion Agent operator runbook
## Deploying
Apply `k8s/configmap.yaml`, `k8s/deployment.yaml`, and `k8s/service.yaml` in that order. The deployment intentionally does **not** contain credentials. Before applying it, provision a Kubernetes Secret named `content-ingestion-agent-secrets` through the cluster's approved secret manager or External Secrets controller. The Secret must provide `github-token` and `sharepoint-client-secret`; do not commit a Secret manifest, token, certificate, or client secret to this repository.
Verify the resulting pod with `kubectl -n <namespace> get pods -l app.kubernetes.io/name=content-ingestion-agent` and inspect only non-sensitive status and logs. Rotate credentials in the external secret manager, then restart the deployment to pick up the rotated values.
## Capability and approval boundary
The agent can read configured GitHub repositories and SharePoint content. Its publication connector can perform the world-changing action of writing/publishing content to the configured CMS. Publication is disabled by default by `PUBLICATION_ENABLED=false` and remains approval-gated by `REQUIRE_PUBLICATION_APPROVAL=true`. Operators must review the proposed changes and explicitly approve a publication request; never grant the runtime identity broader repository or CMS permissions than required.
If publication is enabled for an environment, record the approver, target, change summary, and rollback procedure before deployment. Test ingestion against a non-production source first. To stop publication immediately, set `PUBLICATION_ENABLED=false` in the ConfigMap and roll out the deployment.
## Secret-handling checks
- Credentials are consumed only through `secretRef`/`secretKeyRef` environment bindings.
- ConfigMap data is limited to non-sensitive runtime flags and provider names.
- Do not use `kubectl get secret ... -o yaml` in support output, and do not place secret values in issue reports or logs.
- The workflow and manifests contain no literal credential values.

View File

@@ -1,8 +1,12 @@
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: content-ingestion-agent name: content-ingestion-agent-config
labels:
app.kubernetes.io/name: content-ingestion-agent
data: data:
ENVIRONMENT: production LOG_LEVEL: INFO
REQUIRE_APPROVAL: "true" PUBLICATION_ENABLED: "false"
SHAREPOINT_SITE_URL: https://sharepoint.example.com REQUIRE_PUBLICATION_APPROVAL: "true"
SCM_PROVIDER: github
CMS_PROVIDER: sharepoint

View File

@@ -2,16 +2,67 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: content-ingestion-agent name: content-ingestion-agent
labels:
app.kubernetes.io/name: content-ingestion-agent
spec: spec:
replicas: 1 replicas: 1
selector: selector:
matchLabels: {app: content-ingestion-agent} matchLabels:
app.kubernetes.io/name: content-ingestion-agent
template: template:
metadata: {labels: {app: content-ingestion-agent}} metadata:
labels:
app.kubernetes.io/name: content-ingestion-agent
spec: spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers: containers:
- name: agent - name: agent
image: content-ingestion-agent:latest image: content-ingestion-agent:latest
ports: [{containerPort: 8080}] imagePullPolicy: IfNotPresent
envFrom: [{configMapRef: {name: content-ingestion-agent}}] ports:
readinessProbe: {httpGet: {path: /health, port: 8080}} - name: http
containerPort: 8080
envFrom:
- configMapRef:
name: content-ingestion-agent-config
- secretRef:
name: content-ingestion-agent-secrets
env:
- name: GITHUB_TOKEN
valueFrom:
secretKeyRef:
name: content-ingestion-agent-secrets
key: github-token
- name: SHAREPOINT_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: content-ingestion-agent-secrets
key: sharepoint-client-secret
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 15
periodSeconds: 20
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]

View File

@@ -2,9 +2,13 @@ apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: content-ingestion-agent name: content-ingestion-agent
labels:
app.kubernetes.io/name: content-ingestion-agent
spec: spec:
selector: {app: content-ingestion-agent} type: ClusterIP
selector:
app.kubernetes.io/name: content-ingestion-agent
ports: ports:
- name: http - name: http
port: 80 port: 80
targetPort: 8080 targetPort: http