Skip to content

Commit 6f16daa

Browse files
committed
Merge remote-tracking branch 'origin/alpha' into feat/mimoquage-skip-missing-info
# Conflicts: # packages/app/src/server/api/routers/declarationHelpers.ts
2 parents f7fc781 + af8ad64 commit 6f16daa

71 files changed

Lines changed: 2105 additions & 802 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/rules/audit-logging.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,17 @@ Notes:
144144

145145
### 5. New cron-triggered / system action
146146

147-
Use `logAction` directly with category `system` inside the route handler or
148-
helper that the cron calls. See `/api/audit/cleanup/route.ts` for the canonical
149-
pattern (success + failure self-audit with metadata).
147+
Two patterns are in use, depending on whether the cron runs **inside** the app
148+
(a tRPC procedure or Next.js route called by a CronJob container) or **out of
149+
band** (a standalone `.mjs` script invoked by the CronJob with direct DB
150+
access — see `packages/app/scripts/audit-cleanup.mjs` for the canonical
151+
example, issue #3268).
152+
153+
- **In-app trigger**: use `logAction` directly with category `system` inside
154+
the route handler / helper that the cron calls.
155+
- **Out-of-band script**: self-audit via a raw `INSERT INTO audit.action_log`
156+
statement at the end of the script (success) and in a try/catch arm
157+
(failure, outside the rolled-back transaction so the row survives).
150158

151159
---
152160

@@ -196,10 +204,10 @@ the caller is responsible for sanitisation:
196204
| `export` | 365 days | Data exports and third-party API consumers. |
197205
| `system` | 365 days | Cron-triggered / admin actions. |
198206

199-
The cleanup cron (`/api/audit/cleanup``cleanupAuditLogs`) drops
200-
`read_sensitive` rows after 180 days and everything else after 365 days. This
201-
is enforced at the DB level; the category you choose **defines** the retention
202-
window.
207+
The cleanup cron (`packages/app/scripts/audit-cleanup.mjs`, wired up in
208+
`.kontinuous/templates/audit-cleanup-cron.yaml`) drops `read_sensitive` rows
209+
after 180 days and everything else after 365 days. This is enforced at the DB
210+
level; the category you choose **defines** the retention window.
203211

204212
---
205213

.claude/rules/automation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ Apply these rules **as you write code**, before any agent runs:
114114
- New auth event / cron → direct `logAction` call; `logger.error` must stay synchronous (`void (async () => {...})()`)
115115
- Every new action requires **3 wire-up points**: `AUDIT_ACTIONS.*` constant, `AUDIT_ACTION_CATEGORIES` mapping, and the surface-specific wire (tRPC map / wrapper / direct call)
116116
- `metadata` jsonb must not contain secrets (auto-stripped keys: `password`, `token`, `refresh_token`, `secret`, `client_secret`, `authorization`, `apikey`, `api_key`, `accesskey`, `access_key`, `private_key`)
117-
- DB-layer changes in `~/server/audit/cleanup.ts` → add an integration test (`*.integration.test.ts`, runs via `pnpm test:integration`) — unit tests mock drizzle and miss driver bugs
117+
- DB-layer changes in `packages/app/scripts/audit-cleanup.mjs` (or any file that touches `audit.action_log` via non-trivial SQL) → add an integration test (`*.integration.test.ts`, runs via `pnpm test:integration`) — unit tests mock the DB driver and miss driver bugs
118118

119119
### E2E tests (when relevant)
120120

.github/workflows/e2e.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ jobs:
3232
CLAMAV_HOST: localhost
3333
CLAMAV_PORT: 3310
3434
ADMIN_EMAILS: test@fia1.fr
35-
# Required by env.js but never exercised by E2E tests (the audit
36-
# cleanup route is only called by the K8s CronJob). A dummy value
37-
# that satisfies the `.min(32)` Zod check is enough.
38-
EGAPRO_AUDIT_CLEANUP_TOKEN: e2e-dummy-audit-cleanup-token-not-used-1234567890
3935
steps:
4036
- name: Checkout repository
4137
uses: actions/checkout@v4

.kontinuous/Chart.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
dependencies:
2+
- name: valkey
3+
repository: https://valkey.io/valkey-helm
4+
version: 0.9.4

.kontinuous/env/dev/templates/audit-cleanup.sealed-secret.yaml

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: ConfigMap
2+
apiVersion: v1
3+
metadata:
4+
name: valkey
5+
data:
6+
VALKEY_URL: "redis://valkey:6379"

.kontinuous/env/preprod/templates/audit-cleanup.sealed-secret.yaml

Lines changed: 0 additions & 15 deletions
This file was deleted.

.kontinuous/env/preprod/templates/mail.configmap.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ apiVersion: v1
33
metadata:
44
name: mail
55
data:
6-
MAIL_ENABLED: "false"
7-
SMTP_HOST: ""
6+
# Using MailDev as an in-cluster SMTP catcher until a Tipimail preprod
7+
# sealed-secret is available. The UI is exposed at
8+
# https://maildev-<global.host> via the maildev Ingress.
9+
MAIL_ENABLED: "true"
10+
SMTP_HOST: "maildev"
811
SMTP_PORT: "1025"
912
MAIL_FROM: "no-reply@egapro.preprod.fabrique.social.gouv.fr"
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: maildev
5+
namespace: {{ .Values.global.namespace }}
6+
labels:
7+
app: maildev
8+
spec:
9+
replicas: 1
10+
selector:
11+
matchLabels:
12+
app: maildev
13+
template:
14+
metadata:
15+
labels:
16+
app: maildev
17+
spec:
18+
securityContext:
19+
runAsNonRoot: true
20+
runAsUser: 1000
21+
containers:
22+
- name: maildev
23+
image: maildev/maildev:2.2.1
24+
securityContext:
25+
allowPrivilegeEscalation: false
26+
readOnlyRootFilesystem: true
27+
capabilities:
28+
drop: ["ALL"]
29+
ports:
30+
- name: smtp
31+
containerPort: 1025
32+
- name: web
33+
containerPort: 1080
34+
readinessProbe:
35+
httpGet:
36+
path: /
37+
port: web
38+
initialDelaySeconds: 5
39+
periodSeconds: 10
40+
resources:
41+
requests:
42+
cpu: 10m
43+
memory: 64Mi
44+
limits:
45+
cpu: 200m
46+
memory: 256Mi
47+
volumeMounts:
48+
- name: tmp
49+
mountPath: /tmp
50+
volumes:
51+
- name: tmp
52+
emptyDir: {}
53+
---
54+
apiVersion: v1
55+
kind: Service
56+
metadata:
57+
name: maildev
58+
namespace: {{ .Values.global.namespace }}
59+
spec:
60+
selector:
61+
app: maildev
62+
ports:
63+
- name: smtp
64+
port: 1025
65+
targetPort: smtp
66+
- name: web
67+
port: 1080
68+
targetPort: web
69+
---
70+
apiVersion: networking.k8s.io/v1
71+
kind: Ingress
72+
metadata:
73+
name: maildev
74+
namespace: {{ .Values.global.namespace }}
75+
annotations:
76+
cert-manager.io/cluster-issuer: letsencrypt-prod
77+
nginx.ingress.kubernetes.io/ssl-redirect: "true"
78+
spec:
79+
ingressClassName: nginx
80+
tls:
81+
- hosts:
82+
- maildev-{{ .Values.global.host }}
83+
secretName: maildev-tls
84+
rules:
85+
- host: maildev-{{ .Values.global.host }}
86+
http:
87+
paths:
88+
- path: /
89+
pathType: Prefix
90+
backend:
91+
service:
92+
name: maildev
93+
port:
94+
name: web
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: ConfigMap
2+
apiVersion: v1
3+
metadata:
4+
name: valkey
5+
data:
6+
VALKEY_URL: "redis://valkey:6379"

0 commit comments

Comments
 (0)