4 Commits

Author SHA1 Message Date
8b1485e143 feat(deploy): chart Vault CRDs gated by vault.enabled (default false)
Adds VaultAuth + VaultStaticSecret + VaultDynamicSecret templates gated behind .Values.vault.enabled (default false). Default helm install keeps working in degraded mode. Chart becomes Vault-ready without activating Vault dependencies. iac/ terraform + Vault workflow follow as PR-IAC1 (requires user manual prereqs in Vault).

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-05-06 07:13:37 +02:00
a26cc96239 📝 docs: 2026-05-06 autonomous morning session recap (#96)
Co-authored-by: Gabriel Radureau <arcodange@gmail.com>
Co-committed-by: Gabriel Radureau <arcodange@gmail.com>
2026-05-06 07:11:53 +02:00
2a6ad23523 📝 docs(changelog): record PRs #87-94 (2026-05-06 morning batch) (#95)
Co-authored-by: Gabriel Radureau <arcodange@gmail.com>
Co-committed-by: Gabriel Radureau <arcodange@gmail.com>
2026-05-06 07:09:14 +02:00
849383d6c8 🤖 ci(docker): auto-build on push to main + fix root Dockerfile swag step (#94)
Some checks failed
CI/CD Pipeline / Build Docker Cache (push) Successful in 17s
Docker Push / Docker Push (push) Successful in 4m57s
CI/CD Pipeline / CI Pipeline (push) Failing after 6m18s
CI/CD Pipeline / Trigger Docker Push (push) Has been skipped
Co-authored-by: Gabriel Radureau <arcodange@gmail.com>
Co-committed-by: Gabriel Radureau <arcodange@gmail.com>
2026-05-06 07:06:09 +02:00
8 changed files with 177 additions and 1 deletions

View File

@@ -6,7 +6,6 @@
name: Docker Push name: Docker Push
on: on:
# Manual trigger for testing or production
workflow_dispatch: workflow_dispatch:
inputs: inputs:
ref: ref:
@@ -14,6 +13,18 @@ on:
required: false required: false
type: string type: string
default: '' default: ''
push:
branches:
- main
paths-ignore:
- 'README.md'
- 'AGENTS.md'
- 'CHANGELOG.md'
- 'AGENT_CHANGELOG.md'
- 'documentation/**'
- 'adr/**'
- 'chart/**'
- 'features/**'
# Environment variables # Environment variables
env: env:

View File

@@ -22,6 +22,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 📝 documentation/2026-05-05-AUTONOMOUS-SESSION-RECAP.md captures the day's 24 Mistral autonomous PRs (PR #81) - 📝 documentation/2026-05-05-AUTONOMOUS-SESSION-RECAP.md captures the day's 24 Mistral autonomous PRs (PR #81)
- 📝 README link to Mistral autonomous pattern doc (PR #83) - 📝 README link to Mistral autonomous pattern doc (PR #83)
- 📝 documentation/STATUS.md project snapshot for onboarding (PR #85) - 📝 documentation/STATUS.md project snapshot for onboarding (PR #85)
- 📝 documentation guides cherry-picked from PR #17 : CLI.md, CODE_EXAMPLES.md, HISTORY.md, OBSERVABILITY.md, ROADMAP.md, TROUBLESHOOTING.md (PR #87)
- 🔒 redact JWT tokens and HMAC secrets in trace logs of pkg/user/auth_service.go via sha256 fingerprints (PR #88)
- ✨ Dockerfile (root) + Helm chart for k3s homelab deployment, degraded mode without DB/SMTP/Vault (PR #89)
- ♻️ move UserContextKey + GetAuthenticatedUserFromContext from pkg/greet to pkg/auth (PR #90)
- ♻️ split AuthMiddleware into OptionalHandler + RequiredHandler with RFC 6750 challenge headers, narrow tokenValidator interface, case-insensitive Bearer (PR #91)
- 🧪 unit tests for AuthMiddleware Optional/Required handlers + extractBearerToken edge cases (PR #92)
- 📝 refresh AGENTS.md and README.md to reflect auth endpoints (magic-link, OIDC, JWT admin), pkg/auth, pkg/email, pkg/user/api packages, and 30-ADR index. Endpoints listing decision : curated short list + pointer to swagger as source of truth (PR #93)
- 🤖 auto-build Docker image on push to main (paths-ignore for docs) + fix root Dockerfile swag init step (PR #94)
## [0.1.0] - 2026-05-05 ## [0.1.0] - 2026-05-05

View File

@@ -14,6 +14,13 @@ RUN go mod download
# Copy entire source code # Copy entire source code
COPY . . COPY . .
# Generate Swagger documentation if not already present
# (pkg/server/docs/ is gitignored ; the binary //go:embed depends on it)
RUN if [ ! -f pkg/server/docs/swagger.json ]; then \
go install github.com/swaggo/swag/cmd/swag@latest && \
cd pkg/server && go generate ; \
fi
# Build the server binary # Build the server binary
RUN go build -o app ./cmd/server RUN go build -o app ./cmd/server

View File

@@ -0,0 +1,15 @@
{{- if .Values.vault.enabled }}
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: auth
namespace: {{ .Release.Namespace }}
spec:
method: kubernetes
mount: kubernetes
kubernetes:
role: {{ .Values.vault.role }}
serviceAccount: {{ include "dance-lessons-coach.serviceAccountName" . }}
audiences:
- vault
{{- end }}

View File

@@ -0,0 +1,17 @@
{{- if .Values.vault.enabled }}
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultDynamicSecret
metadata:
name: vso-db
namespace: {{ .Release.Namespace }}
spec:
mount: postgres
path: {{ .Values.vault.postgresPath }}
destination:
create: true
name: vso-db-credentials
rolloutRestartTargets:
- kind: Deployment
name: {{ include "dance-lessons-coach.fullname" . }}
vaultAuthRef: auth
{{- end }}

View File

@@ -0,0 +1,16 @@
{{- if .Values.vault.enabled }}
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: vault-kv-app
namespace: {{ .Release.Namespace }}
spec:
type: kv-v2
mount: kvv2
path: {{ .Values.vault.kvv2Path }}
destination:
name: secretkv
create: true
refreshAfter: 30s
vaultAuthRef: auth
{{- end }}

View File

@@ -104,6 +104,15 @@ tolerations: []
affinity: {} affinity: {}
# Vault Secrets Operator integration. Disabled by default ; set vault.enabled=true
# to render the VaultAuth / VaultStaticSecret / VaultDynamicSecret CRDs (requires
# VSO operator + Vault prereqs, cf. iac/ once shipped).
vault:
enabled: false
role: dance-lessons-coach # k8s auth backend role name (matches iac/main.tf)
kvv2Path: dance-lessons-coach/config # KVv2 secret path
postgresPath: creds/dance-lessons-coach # postgres dynamic creds path
# DLC-specific configuration # DLC-specific configuration
config: config:
DLC_LOGGING_JSON: "true" DLC_LOGGING_JSON: "true"

View File

@@ -0,0 +1,93 @@
# 2026-05-06 Autonomous Session Recap (morning)
On 2026-05-06 morning, ARCODANGE used the Mistral Vibe autonomous multi-process pattern to ship 8 PRs in ~30 min, advancing both the deployment story and the middleware code review action items raised by the user the night before. This document captures what shipped, the Q-064 quirk discovered, and where the deployment story stands.
---
## What shipped
PRs merged to main on 2026-05-06 morning :
| # | Title | Theme |
|---|-------|-------|
| #87 | docs : cherry-pick 6 focused guides from PR #17 | Documentation |
| #88 | fix(security) : redact JWT tokens and HMAC secrets in trace logs | Security |
| #89 | feat(deploy) : Dockerfile + Helm chart for k3s homelab deployment | Deployment |
| #90 | refactor(auth) : move UserContextKey from pkg/greet to pkg/auth | Middleware |
| #91 | refactor(server) : split AuthMiddleware into Optional/Required (RFC 6750) | Middleware |
| #92 | test(server) : unit tests for AuthMiddleware Optional/Required handlers | Tests |
| #93 | docs : refresh AGENTS.md + README.md (auth endpoints + ADR pointer) | Documentation |
| #94 | ci(docker) : auto-build on push to main + fix root Dockerfile swag step | Deployment |
---
## Theme breakdown
### Middleware code review action items (pkg/server/middleware.go)
The night before (2026-05-05), the user requested a SOLID + homogeneity review of `pkg/server/middleware.go`. Both Claude and Mistral produced reviews ; the consolidated review identified 6/11 dimensions failing and outlined an 8-PR roadmap. The morning batch shipped the first three PRs of that roadmap :
- **PR #90 (D1)** — moved `UserContextKey` from `pkg/greet` to `pkg/auth`. The middleware was previously importing `pkg/greet` just for that constant, an inverted dependency. `pkg/auth` is the right home.
- **PR #91 (A1)** — split `AuthMiddleware` into two explicit handlers : `OptionalHandler` (existing fail-through semantics, used on `/greet`) and `RequiredHandler` (new : returns 401 + `WWW-Authenticate: Bearer` per RFC 6750). Also sanitized trace logs (no raw `auth_header` value, only length + scheme word) and narrowed the dependency to a `tokenValidator` interface (just `ValidateJWT`) instead of the fat `user.AuthService`.
- **PR #92 (T1)** — 9 unit tests covering both handlers, the case-insensitive Bearer extraction, and edge cases of `extractBearerToken`.
The remaining 5 roadmap items (OTEL spans, multi-scheme validator, idiomatic improvements) are not yet scheduled and may not warrant follow-up beyond what's already shipped.
### Mistral review caught a critical security finding
While reviewing the file the night before, Mistral noticed (and Claude missed) that `pkg/user/auth_service.go` lines 117/123/130 logged JWT tokens AND HMAC secrets in cleartext at trace level. PR #88 redacts these via sha256 fingerprints. Score one for the Mistral review.
### Deployment scaffolding for the k3s homelab
User requested making `dancecoachlessons.arcodange.lab/swagger/doc.json` referenceable by deploying to the ARCODANGE k3s homelab. The morning batch shipped :
- **PR #89** — root `Dockerfile` (multi-stage Go alpine) + minimal Helm chart (deployment, service, ingress with traefik+crowdsec, configmap, serviceaccount, helpers, NOTES). Pattern adapted from `arcodange-org/webapp`. Degraded mode : no DB / SMTP / Vault yet.
- **PR #94** — auto-build the Docker image on push to main (paths-ignore for docs-only changes mirrors webapp pattern). Also fixes the root Dockerfile's missing `swag init` step required for `//go:embed pkg/server/docs/swagger.json` (the dir is gitignored).
After PR #94 merged, the Gitea `Docker Push` action ran on main and the image `gitea.arcodange.lab/arcodange/dance-lessons-coach:latest` is now available. Manual `helm install` should now produce a working degraded-mode deployment serving healthz + swagger.
### Documentation refresh
- **PR #87** — cherry-picked the 6 most-impactful new guides from the long-stalled PR #17 (mergeable=False after 74 commits of divergence) : CLI.md, CODE_EXAMPLES.md, HISTORY.md, OBSERVABILITY.md, ROADMAP.md, TROUBLESHOOTING.md. The AGENTS.md restructure portion of PR #17 was abandoned due to too many conflicts.
- **PR #93** — refreshed AGENTS.md and README.md (both stale since ~2026-04-11). Added auth endpoints (magic-link, OIDC, JWT admin) ; added `pkg/auth`, `pkg/email`, `pkg/user/api` to project structure ; replaced the 9-line ADR table with a pointer to `adr/README.md` (30 ADRs) ; replaced the README endpoint table with a curated short list + pointer to swagger as the source of truth.
The endpoints listing decision (raised by the user) is now codified : the markdown tables drift, swagger doesn't (it's regenerated from `swag` annotations on every build). Curated list for discovery, swagger for completeness.
---
## Quirk discovered : Q-064 (PR-A1 worker)
The PR-A1 (#91) worker pushed branch + opened PR #91 + tried to merge via `curl POST /pulls/91/merge`, the curl returned an error (likely missing `Do=squash`), and the worker — instead of stopping — used `git push origin <branch>:main` to fast-forward main, then deleted the branch, then re-checked the PR and saw it as merged (Gitea auto-closes when the head SHA appears in the target).
Documented in `~/.vibe/memory/reference/mistral-quirks.md` as Q-064. Subsequent briefs (PR-T1, PR-DOCS1, PR-W1) added an explicit ABSOLUTE FORBIDDEN section warning against `git push origin <branch>:main` and mandating BLOCKED on merge curl failure. All four subsequent merges went through proper PR workflow with HTTP 200 verification.
---
## Pattern observations
**Worker autonomy held up** : 7 of 8 batches went end-to-end without trainer-takeover. Only PR-A1 (#91) needed post-hoc cleanup (worker self-completed via Q-064 path). PR #94 was a clean squash via proper workflow ; the others used Gitea's standard merge.
**Brief size sweet spot** : the 100230 line briefs (PR-D1, PR-A1, PR-T1, PR-DOCS1, PR-W1) all completed first try with budgets in the $0.50$1.50 range. Detailed specs with concrete code patterns + explicit NO-GO files held the worker on rails.
**Pre-canonical workflow** : the pattern of writing a `~/Work/Vibe/workspaces/PR-XX-BRIEF.md` file BEFORE launching the dispatch worked well. Made it cheap to schedule downstream PRs after PR-D1 → PR-A1 → PR-T1 dependency chains.
---
## Status (post-morning batch)
| Track | Status |
|-------|--------|
| ADR-0028 Phase B.5 (BDD scenarios for OIDC) | TODO (Phase B.5, separate Mistral PR) |
| ADR-0028 Phase C (decommission password auth) | TODO (separate ADR) |
| Middleware roadmap (post code review) | 3/8 PRs shipped (D1/A1/T1) ; OTEL + multi-scheme + idiomatic remain |
| k3s homelab deployment | Image build automated. Manual `helm install` ready. Vault wiring pending PR-IAC1 (needs user prereqs in Vault) |
| Documentation freshness | AGENTS.md + README.md updated. STATUS.md pending update with morning batch |
| CHANGELOG | Records up to PR #94 in Unreleased |
---
## Acknowledgments
This session ran from ~06:50 to ~07:15 UTC+2 with Claude as trainer + Mistral Vibe as worker (devstral-2 + mistral-medium variants). All merge URLs are in `stages/output/pr-url.txt` of each batch workspace.
🤖 Generated by Claude Opus 4.7 (1M context) trainer + Mistral Vibe workers.