Commit Graph

17 Commits

Author SHA1 Message Date
svcforge-ci 173acc8612 ci: bump image digests to 60ee0f1cbf
Built and scanned by 60ee0f1cbf. ArgoCD syncs from this commit.

[skip ci]
2026-07-22 03:15:59 +00:00
svcforge-ci 9249051ee2 ci: bump image digests to c691f4f4aa
Built and scanned by c691f4f4aa. ArgoCD syncs from this commit.

[skip ci]
2026-07-22 02:42:54 +00:00
svcforge-ci b2cdcecdc1 ci: bump image digests to e7496562b3
Built and scanned by e7496562b3. ArgoCD syncs from this commit.

[skip ci]
2026-07-22 01:08:19 +00:00
svcforge-ci 3b957a8566 ci: bump image digests to 08a529fa63
Built and scanned by 08a529fa63. ArgoCD syncs from this commit.

[skip ci]
2026-07-21 15:42:05 +00:00
svcforge-ci 95a894d816 ci: bump image digests to c53734d2bc
Built and scanned by c53734d2bc. ArgoCD syncs from this commit.

[skip ci]
2026-07-21 15:05:04 +00:00
svcforge-ci 7918dc2b37 ci: bump image digests to 64b18d2823
Built and scanned by 64b18d2823. ArgoCD syncs from this commit.

[skip ci]
2026-07-21 06:33:09 +00:00
svcforge-ci 51a1bb62c0 ci: bump image digests to 6974b3620f
Built and scanned by 6974b3620f. ArgoCD syncs from this commit.

[skip ci]
2026-07-21 05:59:55 +00:00
svcforge-ci 72296ace84 ci: bump image digests to e971e04d75
Built and scanned by e971e04d75. ArgoCD syncs from this commit.

[skip ci]
2026-07-21 02:52:27 +00:00
svcforge-ci 9c8d10ce1f ci: bump image digests to 7079d6340f
Built and scanned by 7079d6340f. ArgoCD syncs from this commit.

[skip ci]
2026-07-21 02:25:04 +00:00
svcforge-ci d6c1b64512 ci: bump image digests to 76cadca8e3
Built and scanned by 76cadca8e3. ArgoCD syncs from this commit.

[skip ci]
2026-07-20 15:27:19 +00:00
svcforge-ci 66336d3648 ci: bump image digests to a843494627
Built and scanned by a843494627. ArgoCD syncs from this commit.

[skip ci]
2026-07-20 15:01:21 +00:00
Nguyen Minh Phuc 31fa9165ff chart: give the migrate hook its own ServiceAccount
ci / lint (push) Failing after 14m13s
ci / types (push) Has been skipped
ci / unit (push) Has been skipped
ci / integration (push) Has been skipped
ci / security (push) Has been skipped
ci / dockerfile (push) Has been skipped
ci / chart (push) Has been skipped
ci / image (api) (push) Has been skipped
ci / image (reconciler) (push) Has been skipped
ci / image (worker) (push) Has been skipped
ci / bump (push) Has been skipped
The Job ran as the api ServiceAccount, which is an ordinary chart resource.
Hooks are created before the release's ordinary manifests, so on a first
install that account does not exist and the Job never starts:

    Error creating: pods "svcforge-migrate-" is forbidden: error looking up
    service account svcforge/svcforge-api: serviceaccount "svcforge-api" not
    found

Not an ArgoCD quirk — helm orders hooks the same way, so both deploy paths
failed identically. It survived review because the chart was only ever checked
with `helm template` and `helm install --dry-run=server`, and neither creates a
Job. The pod is what fails, so only a real install can catch it.

The new account is a hook at weight -10, ahead of the Job at -5, and is bound
to no Role: the migration talks to Postgres and wants nothing from the
Kubernetes API. automountServiceAccountToken is off for the same reason.

Verified with a real `helm install` into a scratch namespace: STATUS deployed,
job Complete 1/1, four migrations applied, and the hook ServiceAccount was 27s
old against 10s for the ordinary ones — the ordering the bug turned on.
2026-07-20 06:33:31 +00:00
Nguyen Minh Phuc 89ad9625f3 chart: disable externalSecret on this cluster
ci / bump (push) Blocked by required conditions
ci / lint (push) Waiting to run
ci / types (push) Blocked by required conditions
ci / unit (push) Blocked by required conditions
ci / integration (push) Blocked by required conditions
ci / security (push) Blocked by required conditions
ci / dockerfile (push) Blocked by required conditions
ci / chart (push) Blocked by required conditions
ci / image (api) (push) Blocked by required conditions
ci / image (reconciler) (push) Blocked by required conditions
ci / image (worker) (push) Blocked by required conditions
The block describes a ClusterSecretStore named `vault` with HashiCorp-style
key/property refs. This cluster has `oci-vault` — OCI Vault via
InstancePrincipal — whose provider addresses a secret by name and takes a JSON
property, so those remoteRefs do not translate as written. There are no
ExternalSecrets anywhere on the cluster, so the path had never been exercised.

svcforge.secretName still resolves through targetName, so the deployments and
the migrate hook read a Secret named svcforge-secrets, created out of band from
~/.config/svcforge/secrets.env.

This is a deviation and the comment says so. ArgoCD does not manage that
Secret, so prune and selfHeal cannot touch it, and it is the one part of the
deployment that cannot be read from git. Restoring the intended design means
adding oci_vault_secret resources to oci-k8s/infra/vault.tf and repointing
secretStoreRef at oci-vault.
2026-07-20 06:26:13 +00:00
svcforge-ci 1a36f43c69 ci: bump image digests to 37b297bf5c
Built and scanned by 37b297bf5c. ArgoCD syncs from this commit.

[skip ci]
2026-07-20 05:12:26 +00:00
svcforge-ci f2b159ef7e ci: bump image digests to ca21b6e70d
Built and scanned by ca21b6e70d. ArgoCD syncs from this commit.

[skip ci]
2026-07-19 09:18:15 +00:00
Nguyen Minh Phuc c76154aeaa review: fix 26 findings from a 4-agent audit
ci / lint (push) Successful in 34s
ci / unit (push) Successful in 1m41s
ci / types (push) Successful in 1m41s
ci / dockerfile (push) Successful in 18s
ci / security (push) Successful in 1m27s
ci / chart (push) Failing after 1m11s
ci / integration (push) Successful in 1m10s
ci / image (api) (push) Has been skipped
ci / image (reconciler) (push) Has been skipped
ci / image (worker) (push) Has been skipped
ci / bump (push) Has been skipped
CORRECTNESS
- lost-lease race: complete()/fail() did not check ownership, so a worker whose
  lease expired could mark a task done while another worker was running it, or
  requeue a task someone else owned. Reproduced, fixed with a CAS on
  (state, locked_by), pinned by two regression tests.
- worker died on report failure: _run_one's docstring claimed no exception
  escapes the TaskGroup; fail()/complete() were outside the guarded block, so a
  DB blip cancelled every sibling provision on the pod.
- claim query used an INNER join, which could strand a just-claimed task and
  report 'queue empty'. LEFT join.
- InstanceRepo.set_error bypassed the state machine and had no callers. Deleted.
- handle_deprovision ignored its CAS result, so a wrong-state instance kept a
  dangling endpoint and got re-provisioned by the drift check 60s later.
- handle_verify re-notified on every retry: five pages for one halt.

DEPLOY-BREAKING
- the migration Job could never succeed: no Dockerfile copied migrations/, and
  migrate.py resolved the path relative to the source tree, which only works for
  an editable install. Added COPY + SVCFORGE_MIGRATIONS_DIR.
- ServiceMonitor selector did not match the Service: API metrics never scraped.
- SvcforgeReconcilerStale fired permanently from every pod, because the gauge is
  module-level and every service exports it as 0. Scoped to the reconciler job.
- SvcforgeTaskFailed latched forever on a monotonic counter. Now increase()[15m].
- the digest guard accepted the all-zeros placeholder.
- worker terminationGracePeriodSeconds was 60s against a 600s helm timeout.

DEAD CODE THAT SHOULD NOT HAVE BEEN
- adapters/k8s.py was never called, so tenant namespaces were never created and
  the first provision for a new team would fail. Wired into handle_provision.
- adapters/redis.py was never imported by any service. Rate limiting is now wired
  into the API, failing open.
- Settings.check_production() had no callers. Given an explicit environment and
  called from every entrypoint.

OBSERVABILITY
- the API never called obs.setup(): no JSON logs, no trace correlation, log_json
  silently inert.
- LogNotifier's structured fields were discarded by the stdlib->structlog bridge.
- bind_task_context cleared the 'service' binding for the life of every task.
- split tasks_failed into task_attempts_failed and tasks_dead_lettered.

SECURITY
- trivy correctly blocked the worker/reconciler images: helm 3.16.2 and kubectl
  1.31.2 carry CRITICAL Go stdlib CVEs. Bumped to helm 3.21.3 and kubectl 1.35.3,
  which also closes a four-minor skew against the v1.35.3 cluster.

TESTS THAT COULD NOT FAIL
- the concurrency cap test passed on a fully serial worker.
- the alert/metric cross-check asserted a hardcoded list instead of reading the
  chart, so it could not catch a rename on the chart side.
- fixed OTel tracer-provider pollution between test files.

DOCS
- ARCHITECTURE.md: mermaid diagrams, user stories, and the helm-vs-ArgoCD
  guarantee (verified with --dry-run=server).
- AGENTS.md + CLAUDE.md.
- prose sweep for back-and-forth phrasing across 19 files.
2026-07-18 12:13:49 +00:00
Nguyen Minh Phuc 50c2fe2a1e svcforge: reference implementation
ci / lint (push) Successful in 1m19s
ci / unit (push) Failing after 1m2s
ci / integration (push) Has been skipped
ci / types (push) Successful in 1m37s
ci / security (push) Failing after 38s
ci / dockerfile (push) Successful in 14s
ci / image (api) (push) Has been skipped
ci / image (reconciler) (push) Has been skipped
ci / image (worker) (push) Has been skipped
ci / bump (push) Has been skipped
Complete working build of the system learn-python/ teaches.
164 tests, mypy --strict clean, domain coverage 99%.
2026-07-17 10:44:54 +00:00