Commit Graph
156 Commits
Author SHA1 Message Date
arcodangeandClaude Fable 5 40da8893be docs(prd): ADC — accounting decision records, the ADR twin for the books
Operator ask 2026-07-12: an ADR-equivalent for accounting so method
choices are consistent AND justifiable. Accounting scatters this across
permanence des méthodes (PCG 121-5), the annexe, the organisation doc
(PCG 911-3) and audit position memos; the ADC unifies them as one
lightweight versioned record: MADR-lite + base légale/effective-dates/
annexe-impact fields, immutable once Accepted (supersede = the
permanence principle made structural), fiscal.yaml rules cite their
ADC (écriture → règle → ADC → base légale in four hops), annexe
generated from the register, acceptance human-only. Seeds adc-001..007
from decisions already made this exercice; two new obligation-table
rows (121-5, 911-3); expert-comptable agenda updated.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-12 14:22:10 +02:00
arcodange a441dd5c4c Merge pull request 'docs(prd): backlog sharpened for cold sessions — execution footers, splits, D9 parked' (#25) from arcodange/backlog-sharpening into main 2026-07-12 14:07:48 +02:00
arcodangeandClaude Fable 5 42bc8ee42c docs(prd): backlog sharpened for cold sessions — execution footers, splits, D9 parked
- STATUS resume protocol: milestones ordered by due date, skip
  human-gated tops, named entry points (erp#38 / #51 / write-skill
  quartet); every issue now carries an Execution footer.
- Backlog map: +erp#59 (T14 split from #48), +erp#60 (T11 loop split
  from #54), retitles, post-replay markers.
- D9 meeting capture parked (nice-to-have; calls are iPhone-first).
- prd_check.py preserved from the session scratchpad into scripts/
  (the closure protocol references the pattern — now it's runnable).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-12 14:07:16 +02:00
arcodange 53cfbf4023 Merge pull request 'docs(prd): client dossiers — the junction of the three agent families' (#23) from arcodange/client-dossier-synergy into main 2026-07-12 13:48:32 +02:00
arcodangeandClaude Fable 5 185208525e docs(prd): meeting capture decided — Hyprnote free tier, Meetily fallback (D9)
Diarization and Google Calendar sync are both on Hyprnote's free plan,
which satisfies the two operator criteria at once; Meetily (MIT,
diarization in the community core) stays as OSS fallback with sb.py
ICS-matching to compensate its missing calendar sync. Gate: quality
judged on a real bilingual call before the lane is trusted (erp#49).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-12 13:47:46 +02:00
arcodangeandClaude Fable 5 5f2d7b7775 docs(prd): meeting-notes lane is local-first (no proprietary notetaker)
Operator has no Granola account (proprietary, paid, cloud
transcription — misfit with the vault doctrine). The delivery-agents
backlog line now specifies the local transcription lane: Whisper-class
model on the M4 + Ornith summary, as an sb.py job.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 20:35:29 +02:00
arcodangeandClaude Fable 5 44ae6ff323 docs(prd): client dossiers — the junction of the three agent families
Operator insight 2026-07-11: the second brain's client dossiers
(01-Projects/Clients/<client>/) are where the back-office fleet meets
the sales chain and the future delivery agents working on client
projects. Knowledge-layer bullet: agent-owned deposit files (never
edits of human notes), each family feeds and reads the dossier
(billing state + contract facts in; dunning tone, contract scope,
new-business sightings out — the KM 4% settlement clause makes
delivery observations a billing input); vault routing doctrine
(local-first) for confidential client content. Backlog updated with
the 2026-07-11 CRM audit facts (propal/contrat/projet modules empty,
KM retainer terms only in WIP JSON — deferred schedule = T06's source
of truth) and the third family (delivery agents; Granola→vault ingest
as an sb.py job; REX → Mode B evidence → CMS).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 20:32:35 +02:00
arcodange 3df2dd0700 Merge pull request 'docs(prd): AI back-office — agent fleet for daily admin & accounting' (#21) from arcodange/prd-ai-back-office into main 2026-07-11 20:21:04 +02:00
arcodangeandClaude Fable 5 d16f7164cb docs(prd): independent verification — the closer never self-certifies
Operator addition to the closure protocol: the QA gate is held by an
independent verifier subagent — context-free, prompted to REFUTE, repo
+ issues + journals as its only inputs; verdict posted on the milestone,
unresolved refutation blocks. New qa-strategy section extends no-self-
grading to POC exit gates and autonomy promotions (verdict attached to
the artifact it gates), mirroring at process level what the pipelines
do at data level (dual extraction, seeded-wrong fixtures).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 20:19:19 +02:00
arcodangeandClaude Fable 5 e15a6d68c5 docs(prd): milestone closure protocol — QA-gated doc-freshness sweep
Operator requirement: the resume protocol's twin. A milestone closes
only through an 8-step sweep that OPENS with a QA gate (acceptance
criteria re-verified with evidence, test suites green — golden-set
bars, injection fixtures, linter suites incl. seeded-wrong provenance
FAILs, idempotency replay; catalog status flips backed by proving-
protocol evidence; can't pass QA -> shed scope, don't close) and ENDS
with doc-surface QA (link/anchor check, deprecation grep of the claims
the milestone retired, fresh-reader smoke test by a context-free
subagent). In between: STATUS flip, roadmap re-baseline (diamonds never
move), no-tombstone truth-pass of leaves, AGENTS.md/SKILL.md/guidebook
sweep, outward loop (ADRs, memories, second-brain REX). Reader's half:
trust order live system > code > STATUS > leaves > memories; stale
Last Updated = suspect. Summarized as a house rule in factory
AGENTS.md, canonical checklist in the PRD STATUS.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 20:16:13 +02:00
arcodangeandClaude Fable 5 960e204b87 docs(agents): active-backlog pointer in the ecosystem front door
Agents discovering the lab through AGENTS.md now find the decomposed
AI back-office backlog (STATUS map, erp milestones, gateway issues,
factory#22 ADR tracking) and the resume protocol.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 20:08:35 +02:00
arcodangeandClaude Fable 5 16317f5584 docs(prd): STATUS backlog map — phases decomposed into issues
Operator request 2026-07-11: decompose the PRD into less-high-level,
unambiguous work items. 23 self-contained issues filed (context,
deliverables, acceptance criteria, dependencies, PRD links): erp#38-57
across 6 dated milestones (P1 flagship, P2 e-invoicing hard 09-01,
P3 standing fleet, ledger compliance, P4 money loops, P5 fiscal),
telegram-gateway#1-2 (queue D1 + digest/cards), factory#22 (ADR
tracking for D1/D2/D4/D6/D7). STATUS phase tracker now points each
phase at its milestone; resume protocol for future sessions: pick the
top unblocked issue of the earliest open milestone.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 18:22:09 +02:00
arcodangeandClaude Fable 5 58968135d0 docs(prd): anti-hallucination contract for agent writes
Operator requirement (2026-07-11): mechanical measures against
hallucinated values in agent-performed edits. Four deterministic
layers in agent-architecture: (1) no free-text critical fields —
code copies values from validated extraction/bank-feed payloads,
the model never re-types them; (2) provenance anchors per critical
field {source_sha256, raw_excerpt} re-verified by a deterministic
checker against re-extracted source text (locale-normalized);
(3) cross-system corroboration against FRESH bank pulls + arithmetic
/checksum invariants; (4) read-back closes the loop. A failed check
refuses, never repairs. Woven into hub goal, C1 strategy, and QA
write-path (seeded-wrong-value fixtures must FAIL). Proven live:
the books-regularization pack shipped with a standalone
verify-provenance checker — 36 field-level checks green against
source PDFs + fresh Qonto/Wise feeds before the human gate.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 17:41:56 +02:00
arcodangeandClaude Fable 5 8e4186dbeb docs(prd): agent catalog — task→(prompt+model+orchestrator) matrix + agent-facing file syntax
New agent-catalog.md leaf answering three operator directions:
(1) the document surface agents read is now specified — AGENTS.md
orientation maps, SKILL.md with trigger-carrying descriptions
(Use-when/SKIP-for), atom.yaml registry contracts, thin prompt.md
files (no business rules in prompts — rules live in profile files
and validators), schema'd fiscal.yaml/calendar.yaml with
effective_from dates, [AGENT]/[HUMAN] runbooks, env-var-indirected
.mcp.json; same-change freshness rule extended to the fleet.
(2) hermes's telegram-gateway confirmed as THE human channel when
available (cluster-served cards, email fallback; D1 operator-endorsed).
(3) the categorization to prove: seven agent classes (incl. the
LLM-free deterministic controller) and a T01-T17 assignment matrix
with per-row proof gates and statuses (proven / to-prove / not-built),
re-scored monthly from run journals (fallback rate >20% = wrong cell).
New D8 (fleet code home, leaning erp fleet/).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 15:09:28 +02:00
arcodangeandClaude Fable 5 5430e5f3ac docs(prd): dated roadmap leaf — Gantt, milestone spine, re-baselining rule
New roadmap.md: mermaid Gantt (validated) putting the six phases on
calendar time from baseline 2026-07-11 — P2 e-invoicing opens the plan
(ADR D4 target 08-14, two-week fallback before the hard 09-01), P1
flagship in parallel (golden set first, A2 earned ~10-09), ledger-
compliance verifications early September (FY-2026 FEC depends on the
accounting-module answer), P3 standing fleet through autumn (sentinel
24/7 ~11-13), P4 money-loop exit over December, P5 riding the fiscal
calendar (acompte 12-15, CA3 switch 01-01, Q1 filing April, CA12 early
May, AG 06-30), P6 e-reporting proven months before 2027-09-01.
Immovable-milestone table, dependency notes, re-baselining rule
(engineering bars slide, diamonds don't — slips shed scope instead).
Wired: hub pointer + leaves row, poc-plan/STATUS backlinks.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 15:02:02 +02:00
arcodangeandClaude Fable 5 a00f5cb065 docs(prd): sandbox-vs-prod posture + certified-accounting-grade operations
New compliance.md leaf: French bookkeeping obligations mapped to fleet
mechanisms — inaltérabilité (L.123-22) via an append-only production
ledger grammar (create/validate/pay/avoir, never mutate a validated
document) enforced by a promote-plan compliance linter; FEC (L.47 A
LPF) with quarterly export + Test Compta Demat validation (accounting-
module binding flagged as unverified gap); piste d'audit fiable (289
VII CGI) framed as a by-product of journals + tx-id reco + monthly
packs; retention, numbering, copie fiable; loi anti-fraude scoped out
(B2B-only) with BlockedLog as sandbox-first belt-and-braces.

New Environments section in agent-architecture: prod = the ledger
(grammar-bound), sandbox = disposable iso-prod rehearsal (exempt, never
wired to production third parties); side_effect_class -> environment/
credential mapping; POCs write on sandbox only; evals target fresh
checkpoints; irreversible-by-design features trial on checkpoints.

Woven through hub (goal, requirement, success criteria, leaves table),
T03/T05/T15 guardrails, QA (linter suite, pure-append snapshots, FEC
cadence, PAF evidence framing), C2, POC-1 exit criteria.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 14:48:20 +02:00
arcodangeandClaude Fable 5 8920547a98 docs(prd): D4 leaning — Qonto as the plateforme agréée (ex-PDP)
Operator direction: Qonto is the capital-deposit bank, a DGFiP-registered
PA with e-invoicing included in every plan, and the fleet's richest
existing API integration. POC-6 rewritten from shortlist to validation
spike (reception + business-API pull + GED archival + 2027 e-reporting
path for the KM export invoices); C12 residual now names the vendor-
concentration trade-off; terminology refreshed PDP -> PA (renamed by the
administration in July 2025); 2027-09 milestone clarified (e-reporting
for export invoices; emission only if a French B2B client arrives).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 14:39:41 +02:00
arcodangeandClaude Fable 5 31158b05fa docs(prd): integrate the second brain as the fleet's knowledge layer
The PARA Obsidian vault (arcodange/SecondBrain — git-synced, sb.py
digest/inbox/gitea-ingest jobs on the hermes cron ticker, local Ornith
model, mcp-obsidian access) enters the PRD as a first-class component:
new T17 knowledge capture & retrieval fiche, knowledge-layer section in
the architecture (ERP = book of record, vault = context + institutional
memory, append-only idempotent deposits, trusted-but-stale retrieval),
hermes/Ornith recognized as the resident M4 runtime (D2 leaning, new D7
cluster<->vault access decision), foundation ledger row, diagram +
goals updated (mermaid revalidated, 231 links/anchors re-checked green).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 14:35:22 +02:00
arcodangeandClaude Fable 5 45418ff79c docs(prd): backlink factory#21 in STATUS
Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 14:25:57 +02:00
arcodangeandClaude Fable 5 169c8debb4 docs(prd): AI back-office — agent fleet for daily admin & accounting
New PRD tree vibe/PRD/ai-back-office/ (hub + 6 leaves + STATUS): task
inventory T01-T16 with mode operatoire, atom/contract architecture on
the ADR-0003 write gate, four-tier model fleet (Claude/Mistral/M4/Pi),
12 challenges with mitigations, POC plan with exit criteria, QA
strategy with autonomy promotion gates. Index row + bidirectional
backlinks (erp guidebook, safe-prod PRD).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-11 14:25:04 +02:00
arcodange 5a80ec32ae Merge pull request 'feat(argocd): onboard prospection dans l'app-of-apps' (#20) from arcodange/onboard-prospection into main 2026-07-08 17:02:39 +02:00
arcodangeandClaude Opus 4.8 5957439f9f feat(argocd): onboard prospection dans l'app-of-apps
Ajoute prospection à gitea_applications → ArgoCD Application (repoURL
arcodange-org/prospection, path chart, namespace prospection) + image-updater
(digest) sur gitea.arcodange.lab/arcodange-org/prospection:latest.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-08 15:38:45 +02:00
arcodange 9a42346852 Merge pull request 'docs(adr): ADR-0003 — sandbox state lifecycle (iso-prod seed, reset & prod-write isolation)' (#19) from claude/adr-0003-sandbox-reset into main 2026-06-28 20:21:54 +02:00
arcodangeandClaude Opus 4.7 8e69004b4c docs(adr): fill the ADR-0003 ↔ PR backlink (factory#19)
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-06-28 20:21:45 +02:00
arcodangeandClaude Opus 4.7 23d8bc9231 docs(adr): ADR-0003 — sandbox state lifecycle (iso-prod seed, reset & prod-write isolation)
Records how erp-sandbox's DATA is seeded, reset, and kept structurally
incapable of harming prod — the application-data-layer complement to ADR-0001
(which rejected an in-cluster sandbox for INFRA rehearsal) and the lifecycle for
the erp-sandbox instance ADR-0002 stood up.

Decision: (1) iso-prod golden via read-only pg_dump of prod erp, app-scoped to
llx_*; (2) reset = DROP OWNED BY erp_sandbox_role CASCADE + pg_restore
--no-owner --role=erp_sandbox_role into the EXISTING db (no DROP/CREATE DATABASE,
no CREATEDB, no superuser; provisioner-owned infra objects like the pgbouncer
user_lookup function are left untouched); (3) prod-write isolation as a
structural invariant (superuser only in human-gated postgres.yaml CI; DROP
DATABASE gated by ownership — erp_sandbox_role owns only erp-sandbox, never prod
erp/erp_role; sandbox-scoped Dolibarr key; membership-only runtime creds;
host-guard; resettability); plus a human-gated promote via the read-only
dolibarr-data-snapshot diff under a separate prod-write credential.

The reset mechanism + the integrity invariant were validated against the live
erp-sandbox: DROP OWNED BY erp_sandbox_role + app-scoped pg_restore round-trips
to the golden checkpoint using only erp_sandbox_role membership (superuser=false,
createdb=false, not a member of erp_role), proving prod is structurally
unreachable from the sandbox credential.

Drafted via a clean-context agent; mechanism refined from a live prototype.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-06-28 20:21:00 +02:00
arcodange 5c60677171 Merge pull request 'feat(multi-env): Phase D4 — register erp-sandbox ArgoCD Application' (#18) from claude/phaseD-erp-sandbox-argocd into main 2026-06-28 18:36:21 +02:00
arcodangeandClaude Opus 4.7 90498e4f55 feat(multi-env): Phase D4 — register erp-sandbox ArgoCD Application
ADR-0002 Phase D, final step. Adds `envs: { sandbox: {} }` to the erp entry
in argocd/values.yaml, so the Phase B per-env loop in templates/apps.yaml
renders an extra Application "erp-sandbox":
  - source: same erp repo + chart, overlaid with values.yaml + values-sandbox.yaml
  - destination namespace: erp-sandbox (CreateNamespace=true)
  - syncPolicy: automated prune + selfHeal (default)

GitOps activation: on merge to main, the factory app-of-apps re-renders and
ArgoCD creates the erp-sandbox Application, which deploys the Dolibarr chart
into the erp-sandbox namespace. The pod's VSO reads the Vault paths created in
D2/D3 (auth/kubernetes/role/erp-sandbox, postgres/creds/erp-sandbox,
kvv2/erp-sandbox/config) and connects to the erp-sandbox DB created in D1.

Render verified: the only diff vs main is the added erp-sandbox Application;
prod erp + all other apps render byte-identical.

No DNS/TLS change needed (Phase E): *.arcodange.lab is a wildcard in Pi-hole
(CoreDNS forwards to it) and cert-manager holds a *.arcodange.lab wildcard set
as Traefik's default TLS — so erp-sandbox.arcodange.lab resolves + gets HTTPS
automatically once the ingress is up.

Completes Phase D. D1=factory#17, D2=tools#3, D3=erp#12 (all merged).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-06-28 18:35:48 +02:00
arcodange a38c8b39f1 Merge pull request 'feat(multi-env): Phase D1 — provision erp-sandbox Postgres DB + role' (#17) from claude/phaseD-erp-sandbox-postgres into main 2026-06-28 17:09:45 +02:00
arcodangeandClaude Opus 4.7 00a838799b feat(multi-env): Phase D1 — provision erp-sandbox Postgres DB + role
Activates the sandbox environment for the ERP on the Postgres side
(ADR-0002 Phase D). `erp` gains `envs = ["prod", "sandbox"]`, so the
elision flatten now materialises a second instance `erp-sandbox`:
  - database `erp-sandbox`
  - owner role `erp_sandbox_role` (snake-case per the convention)
  - pgbouncer user_lookup function + grants for the new DB

The prod `erp` instance is unchanged (db `erp`, role `erp_role`) — the
apply is purely additive (~6 resources for erp-sandbox, 0 changed,
0 destroyed on everything else). Verified the flatten output with a
standalone tofu apply before pushing.

This is D1 of the Phase D activation. D2 (tools Vault policies),
D3 (erp iac creds + KV), D4 (ArgoCD Application) follow in order.

Refs ADR-0002 (factory#15), Phase B (factory#16).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-06-28 17:05:50 +02:00
arcodange 235ff72ac0 Merge pull request 'feat(multi-env): Phase B — factory machinery env-capable (no activation)' (#16) from claude/multi-env-phaseb into main 2026-06-28 16:53:39 +02:00
arcodangeandClaude Opus 4.7 c00c4cdd5c feat(multi-env): Phase B — make factory machinery env-capable (no activation)
ADR-0002 Phase B. Makes postgres/iac, argocd, and the conventions docs
multi-environment-capable WITHOUT activating any sandbox yet — every app
stays prod-only, so this change is behaviour-neutral:
  - postgres/iac `tofu plan` is a no-op (proven: the elision flatten keys
    are bare app names, db=<app>, role=<app>_role — identical addresses)
  - the argocd apps.yaml render is byte-identical (181→181 lines, diff
    empty) since no app declares `envs`

postgres/iac:
- variables.tf: `applications` becomes set(object({name, envs=optional(["prod"])}))
- main.tf: a `local.app_instances` flatten of applications × envs keyed by the
  elided instance id (env=prod → "<app>"); per-app resources iterate it and
  reference each.key / each.value.{database,role}. For prod-only apps every
  resource address + attribute is unchanged. (main.tf also got a full
  `tofu fmt` pass — the pgbouncer function block reindents 4→2 spaces, which
  is cosmetic; the correctness gate is the CI tofu plan, not the text diff.)
- terraform.tfvars: string entries → { name = "..." } objects.

argocd/templates/apps.yaml:
- after the prod Application, a `range $app_attr.envs` loop renders one extra
  Application per non-prod env: name/namespace `<app>-<env>`, shared repoURL,
  helm.valueFiles [values.yaml, values-<env>.yaml], per-env syncPolicy override.
  Renders nothing while no app sets `envs` → prod render unchanged.

docs:
- doc/runbooks/new-web-app/conventions.md (FR, authoritative): new section
  "Plusieurs environnements pour une même app" — elision rule, suffix rule,
  snake-case owner-role exception, erp/erp-sandbox table, ADR-0002 link.
- vibe/guidebooks/lab-ecosystem/naming-conventions.md (EN mirror): the env
  coordinate section + a "Two sandbox models" section reconciling the
  separate-cluster (ADR-0001, names repeat) vs in-cluster sibling (ADR-0002,
  <env> suffix) strategies; Last Updated bumped; ADR-0002 cross-links.

Activation (erp gets envs=["prod","sandbox"] in postgres tfvars + argocd
values + erp/iac) is Phase D, gated by its own plan review.

Refs ADR-0002 (factory#15). Phase A = tools#2 (merged). Phase C = erp#11 (merged).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-06-28 16:28:28 +02:00
arcodange 8a1a63ee10 Merge pull request 'docs(adr): ADR-0002 — per-application environments via an env coordinate' (#15) from claude/adr-multi-env into main 2026-06-28 16:17:37 +02:00
arcodangeandClaude Opus 4.7 c35b510040 docs(adr): fill the ADR-0002 ↔ PR backlink (factory#15)
Replaces the placeholder References line with the PR URL so the
ADR↔PR crosslink is bidirectional per the AGENTS.md rule.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-06-25 14:56:09 +02:00
arcodangeandClaude Opus 4.7 3961914613 docs(adr): ADR-0002 — per-application environments via an env coordinate
Records the decision to extend the <app> join key with a second
coordinate <env>, governed by an elision rule (env=prod elides → every
existing app's derived names are byte-identical and its tofu plan is a
no-op; non-prod envs take the <app>-<env> suffix, with the Postgres
owner role staying snake-case <app>_<env>_role).

Motivated by the ERP's incoming write-capable AI-agent skill: it needs
an in-cluster sandbox instance (erp-sandbox) with a prod-like Dolibarr
API + isolated database to rehearse writes before a human promotes them
to prod. The ADR reconciles this against ADR-0001 honestly — ADR-0001
rejected an in-cluster sandbox for INFRA-change rehearsal (shared
fleet-wide control planes); ADR-0002 operates one layer up where the
agent's only reach is the app's HTTP API against an isolated DB, so the
fleet blast radius is not in scope. The two are complementary; ADR-0002
does not supersede ADR-0001.

Also:
- vibe/ADR/README.md: index row for 0002 + Last Updated 2026-06-25
- PRD safe-prod-like-environment README: bidirectional back-link to
  ADR-0002 on the Adjacent line + Last Updated 2026-06-25

Authored via the ADR Scribe persona, validated via the Continuity Warden
checklist (no-tombstone, breadcrumb, MADR-lite sections, dead-link scan,
bidirectional links).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-06-25 14:55:19 +02:00
arcodange 801724e1bc Merge pull request 'chore(iac): remove spent R2 import block' (#14) from arcodange/r2-import-cleanup into main 2026-06-24 13:24:09 +02:00
arcodangeandClaude Opus 4.8 7727b244ad chore(iac): remove spent R2 import block
The one-time import block from the previous change reconciled
cloudflare_r2_bucket.arcodange_tf into state (run #29: "Import complete",
"Apply complete! Resources: 1 imported"). It is now a no-op, so remove it.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 13:23:42 +02:00
arcodange e2a79a08a7 Merge pull request 'fix(iac): import existing EU R2 bucket into state' (#13) from arcodange/r2-state-import into main 2026-06-24 13:19:56 +02:00
arcodangeandClaude Opus 4.8 a0fbe5c655 fix(iac): import existing EU R2 bucket into state
Run #28 applied cleanly except cloudflare_r2_bucket.arcodange_tf: the bucket
exists in the EU jurisdiction, but its prior state entry lacked the jurisdiction,
so cloudflare provider >=5.20 read it as not-found, removed it from state, and
then failed to recreate it ("already exists"). Add a config-driven import block
with the jurisdiction-qualified id (<account_id>/<bucket_name>/<jurisdiction>) so
the next apply adopts the real bucket. No-op once reconciled; removable after.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 13:19:32 +02:00
arcodange fc28c52b85 Merge pull request 'fix(iac): pin cloudflare provider + lockfile, trust homelab CA in gitea provider' (#12) from arcodange/iac-provider-fixes into main 2026-06-24 13:03:16 +02:00
arcodange bfa05ff633 Merge pull request 'fix(ci): run factory tofu workflows on the CA-trusting runner' (#11) from arcodange/focused-dirac-151213 into main 2026-06-24 13:02:58 +02:00
arcodangeandClaude Opus 4.8 9b545e6f8f fix(iac): pin cloudflare provider + lockfile, trust homelab CA in gitea provider
With the runner CA fix (#11) the iac workflow now runs far enough to apply,
which exposed two provider problems:

cloudflare drift — `cloudflare/cloudflare` floated on `~> 5` with no committed
lock file, so CI pulled v5.21.1 where `cloudflare_account_token.policies[].resources`
is a JSON string, not a map ("Incorrect attribute value type"). Fix:
- pin to `~> 5.21` and commit a multi-platform `.terraform.lock.hcl`
  (linux_arm64 for the runner + darwin_arm64 for local);
- `jsonencode(...)` the module's policy resources;
- bind the cloudflare_token module to `cloudflare/cloudflare` explicitly (it was
  defaulting to `hashicorp/cloudflare`, pulling a redundant provider);
- stop `.gitignore` from hiding the lock file (the old `.terraform.*` rule did).

gitea provider TLS — it runs inside the dflook/terraform-apply container, which
doesn't trust the homelab CA (only the ubuntu-latest-ca runner does), so it
failed `x509: certificate signed by unknown authority` reaching
gitea.arcodange.lab. Fix: feed it the homelab CA via the provider's `cacert_file`
(TF_VAR_gitea_cacert_file -> the homelab.pem the workflow already materializes).

Validated locally with `tofu validate` + provider-schema inspection (no prod
calls). Complements #11. Out of scope (need a live run / operator): the OVH
consumer-key scope, and the R2 bucket "not found" on refresh (a state reconcile).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 12:56:46 +02:00
arcodangeandClaude Opus 4.8 e5c537a967 fix(ci): run factory tofu workflows on the CA-trusting runner
After the move to the self-signed internal DNS (gitea.arcodange.lab /
vault.arcodange.lab), the default `ubuntu-latest` runner image does not
trust the homelab CA, so the `uses:` clone of the vault-action over HTTPS
fails TLS verification. webapp's workflows already moved to the
`ubuntu-latest-ca` runner (whose image ships the homelab CA); apply the
same to the factory `iac` and `postgres` tofu workflows.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 11:22:54 +02:00
arcodange 3b0919b804 Merge pull request 'docs(vibe): bootstrap vibe/ knowledge tree + ecosystem AGENTS.md' (#10) from arcodange/focused-dirac-151213 into main
Reviewed-on: #10
2026-06-24 11:01:09 +02:00
arcodangeandClaude Opus 4.8 053b04337a chore: gitignore .claude/worktrees
Per-session Claude Code checkouts live under .claude/worktrees/<slug>/
on the trunk; keep them out of git so the main checkout stays clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 10:55:43 +02:00
arcodangeandClaude Opus 4.8 1824a1885d docs(vibe): add maintenance rule to the ansible + opentofu sub-hubs
The two factory-provisioning sub-hubs were the only guidebook index pages without
the "alter a documented component -> update its page in the same PR" reminder that
every sibling hub carries. Add a scoped maintenance rule to each, pointing back to
the factory-provisioning maintenance rule and the guidebooks' Rules to contribute,
so no folder hub silently drifts.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-23 23:42:24 +02:00
arcodangeandClaude Opus 4.8 2d76eb45c1 docs(vibe): add new-tool and new-app runbooks (grounded in real PRs)
Two agent-oriented runbooks under vibe/runbooks/ with [AGENT]/[HUMAN] step
markers, grounded in real diffs:

- new-tool.md : add a platform component to the tools repo so ArgoCD deploys it
  into the tools namespace (wrapper Chart.yaml + the tool library + a row in
  chart/values.yaml; optional iac/ for secrets). Mirrors the prometheus/crowdsec
  additions.
- new-app.md  : stand up a brand-new application across THREE repos (app +
  factory + tools) with the strict ordering dependency and the TERRAFORM_SSH_KEY
  pitfall. Phase-by-phase mapped to the dance-lessons-coach onboarding PRs
  (#89/#97/#98/#99/#100), factory #1/#2, tools #1; the FR doc/runbooks/new-web-app
  is linked as the detailed companion.

2 mermaid diagrams MCP-validated; zero dead links across the vibe tree.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-23 22:22:09 +02:00
arcodangeandClaude Opus 4.8 7bf83e75ed docs(vibe): add erp/ guidebook (Dolibarr deployment + backup/recovery + ops)
Dedicated tree-docs guidebook under vibe/guidebooks/erp/ for the lab's most
data-critical app, cross-linked from the applications hub (bidirectional):

- README.md             : Dolibarr 22.0.4 on Postgres; data-criticality; overview
  diagram; the Vault-unseal-before-scale recovery ordering (CAUTION).
- deployment.md         : upstream image + custom entrypoint (MySQL->psql), the
  50Gi Longhorn RWX documents PVC, Vault CRDs + the shared app_roles iac, init
  scripts (conf.php creds, table-ownership), ingress, CI.
- backup-and-recovery.md: the Ansible CronJob pg_dump (daily 04:00, 15-day
  retention) + restore Job (scale-0 -> restore -> scale-1); the cluster recovery
  ordering (Longhorn -> Vault unseal -> erp scale-up).
- operations.md         : the read-only bin/arcodange CLI, static/company.json,
  Deno+Playwright tests, day-2 ops.

erp code via full gitea URLs; CLUSTER_RECOVERY.md by name; 2 mermaid diagrams
MCP-validated; zero dead links.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-23 22:12:11 +02:00
arcodangeandClaude Opus 4.8 4823394e0e docs(vibe): add applications/ guidebook (webapp + url-shortener)
Tree-docs guidebook under vibe/guidebooks/applications/ documenting the common
app pattern and two contrasting archetypes, drilling into lab-ecosystem/01-factory
(bidirectional):

- README.md  : the shared app pattern (repo = Dockerfile + chart + optional iac +
  CI; ArgoCD app-of-apps; the <app> join key; .fr vs .lab ingress conventions) +
  a two-archetype comparison.
- webapp.md  : canonical Go + Postgres exemplar (chart, VaultAuth/Static/Dynamic
  CRDs, inline iac vs the shared app_roles module, CI); notes the current nuance
  that the live pod still uses the static pgbouncer_auth DATABASE_URL.
- url-shortener.md : Rust + SQLite-on-Longhorn-RWO counterpart (single replica,
  no iac/no Vault, CI mirrors the upstream image); the power-cut recovery story.

erp is referenced in prose only (its own guidebook lands next). Sibling-repo code
via full gitea URLs; 2 mermaid diagrams MCP-validated; zero dead links.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-23 21:58:36 +02:00
arcodangeandClaude Opus 4.8 548dacfc44 docs(vibe): add tools/ and cms/ guidebooks
Two code-grounded tree-docs guidebooks under vibe/guidebooks/, drilling into the
lab-ecosystem 02-tools and 03-cms pages (bidirectional):

- tools/  : hub + components.md (Vault+VSO, Prometheus, Grafana, CrowdSec,
  pgbouncer, Redis/KeyDB, Plausible, ClickHouse; pgcat/tool as Tier-2) +
  secrets-and-vso.md (Vault engines/auth, the app_roles/app_policy modules =
  the <app> join-key machinery, VSO CRDs, secret-paths inventory).
- cms/    : hub + site.md (Nuxt + dual Pages/k3s deploy) + cloudflare.md
  (zone via OVH->CF, Pages, cloudflared tunnel, Turnstile, R2 state) +
  zoho-email.md (OAuth, MX/SPF/DKIM/DMARC/BIMI, the 7 aliases).

Sibling-repo code linked via full gitea URLs; vibe-internal links bidirectional.
Reconciled the cloudflared tunnel token path to kvv2 cms/cloudflared (the chart
VaultStaticSecret is kv-v2; the kvv1 tofu reference is a commented-out stub).
6 mermaid diagrams MCP-validated; zero dead links. Lab Cartographer cohort.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-23 21:41:15 +02:00
arcodangeandClaude Opus 4.8 dbe32161dc docs(vibe): add factory-provisioning guidebook (Ansible + OpenTofu)
Deep, code-grounded tree-docs guidebook under vibe/guidebooks/factory-provisioning/,
explored from the actual playbooks/roles and tofu code:

- Hub: the two provisioning engines (operator-run Ansible vs CI-applied OpenTofu),
  a green-field bring-up flow, master index, maintenance rule.
- ansible/ sub-tree: ordered pages 01-system .. 06-recover, an inventory & variables
  concept page, and a Tier-1/Tier-2 roles reference (hashicorp_vault, step_ca,
  crowdsec, pihole, deploy_docker_compose + the gitea_* family and helpers).
- opentofu/ sub-tree: factory-iac (Cloudflare/OVH/GCP/Gitea/Vault edge +
  cloudflare_token module), postgres-iac (per-app DB/role/pgbouncer lookup),
  ci-apply-flow (Gitea OIDC-JWT -> Vault -> auto-approve apply).

Cross-linked bidirectionally with the lab-ecosystem guidebook and the safe-env
ADR/PRD (the sandbox rehearses exactly these engines). 14 mermaid diagrams
MCP-validated; zero dead links. Authored by the Lab Cartographer cohort.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-23 21:11:51 +02:00