Test plan
This page is assembled from three sources: e2e/platform/plan.json (what each feature has to prove, where, how urgent and how hard), FEATURES.md (how far the feature is built) and the test sources (which already name it). The platform itself - targets, fixtures, CI chain - is described on Test platform. Feature titles come from FEATURES.md, which is written in French.
Targets
| Target | |
|---|---|
U |
Go unit and package tests (make test / test-ee) |
I |
Integration suite (Playwright) against one gateway process, CE and EE |
C1 |
docker compose, one instance, SQLite - the published docker-compose.yml / .ee.yml |
CC |
docker compose cluster: 3 gateways + PostgreSQL + a load balancer (EE) |
S1 |
Docker Swarm, one replica - the published stack.swarm.yml |
SC |
Docker Swarm, 3 replicas on PostgreSQL (EE) |
K1 |
kind + the Helm chart, values-ce-one-node / values-ee-one-node |
KC |
kind + the Helm chart, values-ee-cluster on PostgreSQL (EE) |
KO |
kind with OpenShift's rules: namespace under Pod Security 'restricted', the pod run as an arbitrary uid from a namespace range with group 0 (what the restricted SCC does), the chart's values unchanged |
OK |
MicroShift built from OKD, one node in a container on the runner: the real restricted-v2 SCC and the real router (e2e/platform/okd/run.sh), on every pipeline and a gate of the image it publishes |
Priorities
- P0 - blocks a release: the image, the targets, the cluster and the upgrade path
- P1 - the features people deploy Meerkat for, proved through the image
- P2 - the rest of what is built, proved where the platform adds something the unit tests cannot
- P3 - covered well enough by the unit and integration suites; on the platform when convenient
- - - not built, retired, or nothing to test
In numbers
| easy | medium | hard | not built | nothing to test | Total | |
|---|---|---|---|---|---|---|
| P0 | 19 | 9 | 28 | |||
| P1 | 46 | 22 | 68 | |||
| P2 | 74 | 21 | 4 | 99 | ||
| P3 | 61 | 3 | 3 | 67 | ||
| - | 14 | 4 | 18 |
Platform-wide checks
What belongs to no single feature: deploying, upgrading, losing a node, running for hours.
| ID | Area | What has to be proved | Targets | Editions | Priority | Feasibility |
|---|---|---|---|---|---|---|
| X-01 | Deployment | Smoke on every target: image starts, admin signs in, a route proxies to httpbin, the admin API answers, the console loads. | C1 S1 K1 |
CE, EE | P0 | easy |
| X-02 | Upgrade | Upgrade in place from the previous release (found, not pinned): compose pull + up, helm upgrade, stack deploy - data and sessions kept. | C1 CC K1 |
CE, EE | P0 | medium |
| X-04 | Cluster | Rolling update of a 3-replica deployment under constant traffic: no request lost beyond the drain window. | KC |
EE | P0 | medium |
| X-05 | Cluster | Kill a node during traffic: the others keep serving, sessions survive, the lock holder changes. | CC KC |
EE | P0 | medium |
| X-03 | Upgrade | Downgrade refused: the previous image on a newer database stops with a message naming both versions. | C1 |
CE, EE | P1 | easy |
| X-06 | Cluster | PostgreSQL restart: nodes reconnect, readiness drops and comes back, no data lost. | CC KC |
EE | P1 | medium |
| X-07 | Cluster | Exactly-once jobs across nodes: scheduled call, daily digest, ACME issuance, retention purge. | CC |
EE | P1 | easy |
| X-08 | Deployment | Published ports read from the runtime (Docker socket, swarm service, k8s Service) and used in the TLS links and redirects. | C1 S1 K1 |
CE, EE | P1 | easy |
| X-09 | Deployment | Helm: install, upgrade with --reuse-values (new defaults still applied), uninstall leaves no orphan; chart values matrix (one node CE/EE, cluster EE). | K1 |
CE, EE | P1 | easy |
| X-11 | Edition | Edition matrix: the same scenario file played against CE and EE, each expecting its own answers (422/lock vs allowed). | C1 |
CE, EE | P1 | easy |
| X-12 | Edition | Configuration portability: export from EE, import into CE (EE parts named and left out), export from CE, import into EE. | C1 |
CE, EE | P1 | easy |
| X-17 | Deployment | Behind a reverse proxy (Traefik/ingress-nginx): X-Forwarded-* trusted only from it, client IP right in logs and rate limits. | C1 K1 |
CE, EE | P1 | easy |
| X-19 | Cluster | Vault key mismatch between nodes is detected and named, never silently half-working. | CC |
EE | P1 | medium |
| X-21 | Deployment | OpenShift compatibility on kind: the chart installs under Pod Security 'restricted' with an arbitrary uid and group 0, no runAsUser/fsGroup pinned by the chart; the gateway writes /data, migrates, serves, and the snapshot download works. | KO |
CE, EE | P1 | easy |
| X-23 | Deployment | A real OpenShift (MicroShift from OKD): the published chart admitted by the restricted-v2 SCC under a uid the cluster chose, the store writing /data, both planes behind Routes, the mount helper admitted and serving a volume as the workload's uid. | OK |
CE, EE | P1 | easy |
| X-10 | Deployment | Swarm: secrets and configs mounted, replicas converge, update order start-first. | S1 SC |
CE, EE | P2 | easy |
| X-13 | Security | Image hygiene: non-root user, no capability, no privilege escalation, no shell needed, Trivy scan without critical CVE; read-only root filesystem with an emptyDir on /tmp (the snapshot download writes a temporary file). | C1 |
CE, EE | P2 | medium |
| X-14 | Deployment | arm64 image runs the smoke suite (native runner). | C1 |
CE, EE | P2 | medium |
| X-15 | Soak | Soak: 4 hours of mixed traffic on a cluster; memory and goroutines flat, no error budget burnt. | CC |
EE | P2 | hard |
| X-16 | Performance | Load smoke: N requests/s through the image within a latency budget, published beside the benchmarks. | C1 |
CE, EE | P2 | medium |
| X-18 | Lifecycle | Graceful shutdown: SIGTERM drains in-flight requests, closes HTTPS doors, exits 0 within the grace period. | C1 |
CE, EE | P2 | easy |
| X-20 | Lifecycle | Time and timezone: TZ env honoured in digests and schedules. | C1 |
CE, EE | P2 | easy |
| X-22 | Deployment | Static check of the rendered chart for every values file: no pinned uid, no privileged field, no hostPath, no port below 1024 (kube-linter / a rule script), so a change that would break OpenShift fails on the push, not at a customer's. | KO |
CE, EE | P2 | easy |
Sign-in
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| AUTH-01 | Pages du flux _(built)_ | Every sign-in page renders and submits through the image, in light and dark, on a fresh install. | I C1 |
CE, EE | P1 | easy | none |
| AUTH-02 | Mot de passe _(built)_ | Password sign-in through the shipped image: right password in, wrong one refused, the session cookie set on each scheme. | I C1 K1 |
CE, EE | P0 | easy | none |
| AUTH-03 | LDAP / AD _(built)_ | Search-then-bind against OpenLDAP and Samba AD on the platform network; groups collected; CE refuses the provider. | I C1 KC |
EE | P1 | medium | e2e 1 |
| AUTH-04 | OIDC _(built)_ | OIDC sign-in against Dex on the platform network, behind the published ports (redirect URI = the outside address). | I C1 K1 |
CE, EE | P1 | medium | none |
| AUTH-05 | Étapes de connexion _(partly built)_ | Step ordering (password, code, organisation) on the image; a pending step cannot be skipped by URL. | I |
CE, EE | P2 | easy | Go 1 |
| AUTH-06 | JWT vers l'amont _(built)_ | The JWT a service receives verifies against the JWKS of the internal plane (:7070/.well-known/jwks.json), from ANY node of a cluster; the application port does not serve it. | I CC |
CE, EE | P1 | easy | Go 1 |
| AUTH-07 | Rotation des clés _(built)_ | Key rotation on one node: the others sign with the new key and still publish the old one until it expires. | U CC |
CE, EE | P1 | medium | none |
| AUTH-08 | Cookie de session _(built)_ | Session cookie: per-install suffix, __Host- over HTTPS, survives a pod restart (state in the store), valid on every node. | I C1 CC |
CE, EE | P0 | easy | none |
| AUTH-09 | Jetons d'API _(built)_ | API tokens: data-plane token reaches a route, admin token reaches the API, neither reaches the other plane. | I C1 |
CE, EE | P1 | easy | Go 1, e2e 1 |
| AUTH-10 | Politique de mots de passe _(built)_ | Policy refusals named; temporary password expires after its window. | U I |
CE, EE | P2 | easy | none |
| AUTH-11 | Anti-force brute _(built)_ | Repeated failures answer 429, and the counter is shared: failing on node A then B still trips it. Failures on one account from many addresses ask for the picture code (an unknown name exactly the same), never lock it, and mail the owner once per window. | I CC |
CE, EE | P1 | medium | none |
| AUTH-12 | Auto-inscription _(built)_ | Self sign-up with the mail sink: account pending, verification mail received, account usable. | I C1 |
CE, EE | P2 | easy | Go 1 |
| AUTH-13 | Historique de connexions _(built)_ | History lists the sign-in with this browser badged. | I |
CE, EE | P3 | easy | none |
| AUTH-14 | Déconnexion _(built)_ | Sign-out on node A ends the session on node B too; a GET /logout from a page of the site signs out at once, one from elsewhere or a prefetch only asks first. | I CC |
CE, EE | P1 | easy | Go 1 |
| AUTH-15 | Passkeys _(partly built)_ | Passkey enrol and sign-in with a virtual authenticator (Chromium CDP), behind HTTPS on the published port. | I |
CE, EE | P2 | hard | none |
| AUTH-16 | Code par e-mail _(partly built)_ | Code by e-mail: code received in the mail sink, accepted once, expired after its TTL. | I C1 |
CE, EE | P2 | easy | e2e 2 |
| AUTH-17 | Passwordless _(partly built)_ | A passwordless account signs in by passkey or code only. | I |
CE, EE | P3 | easy | none |
| AUTH-18 | Non-cumul des facteurs _(partly built)_ | Two factors of the same kind are not counted twice. | U |
CE, EE | P3 | easy | none |
| AUTH-19 | SAML _(built)_ | SAML: a sign-in against a real identity provider (SimpleSAMLphp) creates or matches the account; a forged, unsigned or wrapped assertion is refused; the CE build offers no SAML provider. | U C1 |
EE | P2 | medium | Go 1 |
| AUTH-20 | Kerberos _(not built)_ | Not built (Kerberos). | - | EE | - | not built | none |
| AUTH-21 | Mot de passe oublié _(built)_ | Forgotten password: mail in the sink, link works once, old sessions revoked. | I C1 |
CE, EE | P1 | easy | Go 1 |
| AUTH-22 | Vérification d'e-mail _(built)_ | E-mail verification mail received and honoured: a link on a name a placed certificate covers, reached over the gateway's own TLS, or on a name declared reached through a proxy that terminates TLS (in plain HTTP behind it, the link still https); a code, and no link, anywhere else - a foreign Host never lands in a mail, and a declared name triggers neither the redirect nor HSTS. | I C1 |
CE, EE | P2 | easy | Go 1 |
| AUTH-23 | Alertes de sécurité _(partly built)_ | Security alerts sent for the events covered: password changed, address changing, too many failed sign-ins on the account (once per window, never for an unknown name). | U |
CE, EE | P3 | easy | none |
| AUTH-24 | Autorité locale _(built)_ | Local authority can be disabled while an external one signs in. | I |
CE, EE | P2 | easy | Go 4 |
Second factor
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| MFA-01 | TOTP _(built)_ | TOTP enrol and challenge (code computed by the test), secret sealed in the store (no base32 secret in a DB dump). | I C1 |
CE, EE | P1 | easy | none |
| MFA-02 | Code de secours par e-mail _(built)_ | Backup code by e-mail through the mail sink. | I C1 |
CE, EE | P2 | easy | none |
| MFA-03 | Navigateurs de confiance _(built)_ | Trusted browser skips the challenge for its TTL, then asks again. | I |
CE, EE | P2 | easy | none |
| MFA-04 | MFA obligatoire _(partly built)_ | Mandatory MFA forces enrolment at next sign-in. | I |
CE, EE | P2 | easy | none |
| MFA-05 | État du flux en base _(built)_ | A sign-in started on node A finishes on node B (flow state in the store). | CC |
CE, EE | P1 | medium | none |
Roles and access
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| RBAC-01 | Rôles hiérarchiques _(built)_ | A parent role implies its children at a route. | U I |
CE, EE | P2 | easy | Go 1, e2e 1 |
| RBAC-02 | Groupes _(built)_ | Group roles reach the JWT sent upstream. | U I |
CE, EE | P2 | easy | none |
| RBAC-03 | Groupe par organisation _(built)_ | Per-organisation groups do not leak across organisations. | I |
CE, EE | P2 | easy | Go 2 |
| RBAC-04 | Périmètres d'administration _(built)_ | The access matrix: every admin endpoint x every profile, allowed and refused (scenarios.json) - played against the IMAGE too. | I |
CE, EE | P0 | easy | none |
| RBAC-05 | Capacités du compte _(built)_ | Capabilities narrow the console and the API alike. | U I |
CE, EE | P2 | easy | Go 6, e2e 1 |
| RBAC-06 | Accès par route _(built)_ | Route access levels (public, signed in, organisation, role) on the data plane of the image. | I C1 |
CE, EE | P0 | easy | Go 2, e2e 2 |
| RBAC-07 | Accès par endpoint _(built)_ | Per-endpoint rules from a deposited OpenAPI: closed operation refused, exception allowed. | U I |
CE, EE | P1 | easy | Go 1 |
| RBAC-09 | Propagation à l'amont _(built)_ | Roles reach the upstream in the configured header shape. | U I |
CE, EE | P2 | easy | none |
| RBAC-10 | Règles de groupe _(built)_ | Group rules from an LDAP group / OIDC claim assign membership at sign-in; CE refuses. | I C1 |
EE | P2 | medium | none |
| RBAC-11 | Impersonation _(not built)_ | Not built (impersonation). | - | CE, EE | - | not built | none |
| RBAC-12 | Rôles déclarés par l'application _(built)_ | The roles a route's OpenAPI declares are shown per operation, imported into the catalogue with a prefix and a tag, and forwarded under the application's names to whoever holds the mapped role. | U I |
CE, EE | P2 | easy | e2e 1 |
Account model
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| MODEL-01 | Champs de compte _(built)_ | Custom account fields validated and forwarded. | U I |
CE, EE | P3 | easy | none |
| MODEL-02 | Fenêtre de validité _(built)_ | An account outside its window is refused at sign-in with the date. | U I |
CE, EE | P2 | easy | Go 1 |
Organisations
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| TENANT-01 | Organisations _(built)_ | Organisations: CE has one, EE several (multi mode switch refused on CE). | I C1 |
CE, EE | P1 | easy | none |
| TENANT-02 | Membres _(built)_ | Membership join/leave and admin badge in both modes. | I |
CE, EE | P2 | easy | Go 1, e2e 1 |
| TENANT-03 | Organisation active _(built)_ | Organisation chooser at sign-in, active organisation in the JWT. | I |
EE | P2 | easy | none |
| TENANT-04 | Heures ouvrées _(partly built)_ | Working hours refuse outside the window (clock injected); ignored on CE. | I |
EE | P2 | medium | Go 1 |
| TENANT-05 | TTL de session _(partly built)_ | Session TTL per organisation. | U |
CE, EE | P3 | easy | none |
| TENANT-06 | Isolation _(built)_ | Tenant isolation: an organisation's admin cannot read or write another's objects (matrix). | I |
EE | P0 | easy | none |
| TENANT-07 | Export d'une organisation _(partly built)_ | Export carries organisations as documented. | U |
CE, EE | P3 | easy | none |
| TENANT-08 | Mono ou multi-organisation _(built)_ | Single/multi mode switch, and CE stays single. | I |
EE | P1 | easy | none |
Routing
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| ROUTE-01 | Routes à chaud _(built)_ | A route saved through the API serves at once, on every node of a cluster (change bus), without restart. | I C1 CC |
CE, EE | P0 | easy | none |
| ROUTE-02 | Attributs de route _(built)_ | Route attributes (strip prefix, host rewrite, headers) as seen by httpbin. | U I |
CE, EE | P2 | easy | none |
| ROUTE-03 | Prédicats _(built)_ | Each of the eleven predicates matches and refuses as documented, against httpbin. | U I |
CE, EE | P1 | easy | none |
| ROUTE-04 | Filtres requête _(built)_ | Request filters (headers, rewrite, body limits) observed upstream on httpbin. | U I |
CE, EE | P1 | easy | Go 1 |
| ROUTE-05 | Filtres réponse _(partly built)_ | Response filters (headers, CORS, cache-control) on proxied and own answers. | U I |
CE, EE | P2 | easy | none |
| ROUTE-07 | Timeouts _(built)_ | Timeouts: an upstream that does not answer within the response bound gets 504 at the configured time, not before; one that refuses or cannot be reached gets 502 near the connect bound; a body already started is never cut. | U I C1 |
CE, EE | P1 | easy | Go 1 |
| ROUTE-08 | Rate limiting _(partly built)_ | Rate limit answers 429 with Retry-After past the bound, counted per node (sharing the bound across nodes is QUOTA-04). | U I |
CE, EE | P1 | medium | none |
| ROUTE-09 | Disjoncteur _(built)_ | Circuit breaker opens on a failing upstream (status endpoint) and half-opens after the delay. | I C1 |
CE, EE | P1 | medium | none |
| ROUTE-10 | Aucune route par défaut _(built)_ | A fresh install answers no route by default (no open proxy). | I C1 |
CE, EE | P0 | easy | Go 1 |
| ROUTE-11 | Sonde d'amont _(built)_ | Upstream probe marks a route's target reachable or not. | I |
CE, EE | P2 | easy | none |
| ROUTE-12 | Import / export _(built)_ | Route export re-imports to the same routes. | I |
CE, EE | P2 | easy | none |
| ROUTE-13 | WebSocket _(built)_ | WebSocket through the gateway (echo service), through every ingress of each target. | I C1 K1 |
CE, EE | P1 | easy | none |
| ROUTE-14 | Compression et HTTP/2 _(partly built)_ | h2 negotiated over the HTTPS door (ALPN); upstream compression passed through. | I C1 |
CE, EE | P2 | easy | Go 1 |
| ROUTE-15 | Testeur de routage _(built)_ | Routing tester names the winning route. | I |
CE, EE | P3 | easy | none |
| ROUTE-16 | Cible unique _(built)_ | Single target enforced. | U |
CE, EE | P3 | easy | none |
| ROUTE-17 | Réponse par gabarit _(built)_ | Template response renders the caller's identity. | U I |
CE, EE | P2 | easy | none |
| ROUTE-22 | Servir des fichiers _(built)_ | A files route serves what was uploaded on it, with its type, an ETag and CORS, and travels in an export. | I |
CE, EE | P2 | easy | Go 1 |
| ROUTE-18 | Rôles envoyés _(built)_ | Roles header sent upstream. | I |
CE, EE | P2 | easy | none |
| ROUTE-19 | REMOTE_USER _(built)_ | REMOTE_USER header sent upstream. | I |
CE, EE | P3 | easy | none |
| ROUTE-20 | gRPC _(partly built)_ | gRPC unary and streaming through the gateway (grpc echo), grpc-status counted; h2c and TLS upstreams. | I C1 K1 |
CE, EE | P1 | medium | Go 1 |
| ROUTE-21 | Extensions _(not built)_ | Not built (extensions). | - | CE, EE | - | not built | none |
Services
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| SVC-01 | Route autoportante _(built)_ | A self-contained route (target in the route) proxies with no other object. | I |
CE, EE | P2 | easy | none |
| SVC-02 | Découverte cluster _(partly built)_ | Discovery lists containers / swarm services / k8s services with the rights the chart and compose files grant; published ports read on each. | C1 S1 K1 KO |
CE, EE | P1 | medium | e2e 1 |
| SVC-03 | Route simple _(built)_ | Simple route wizard result serves. | I |
CE, EE | P3 | easy | none |
| SVC-04 | État des amonts _(built)_ | Upstream health shown down when the service is scaled to 0, up when back. | I K1 |
CE, EE | P2 | medium | e2e 1 |
| SVC-07 | Runtime suivi par événements _(partly built)_ | Scaling a service from 3 to 2 replicas turns its route orange (2/3) and back to green, without reloading the screen; the image it runs shows beside the upstream. | I K1 |
CE, EE | P2 | medium | none |
| SVC-05 | Applications _(not built)_ | Not built (applications). | - | CE, EE | - | not built | none |
| SVC-06 | Inventaire d'endpoints _(partly built)_ | Endpoint inventory from a deposited spec. | U |
CE, EE | P3 | easy | Go 1 |
Injected UI
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| UIF-01 | base href _(partly built)_ | An app published under a prefix loads its assets (mount slash redirect). | I |
CE, EE | P2 | easy | none |
| UIF-02 | Injection HTML _(built)_ | HTML injection present on UI routes, absent on API routes; a route's own blocks land at their place in the list's order, and an uploaded file is linked from /meerkat/route-assets/ and served with a lasting cache. | I |
CE, EE | P2 | easy | none |
| UIF-03 | Bouton utilisateur _(built)_ | User button renders and signs out. | I |
CE, EE | P2 | easy | Go 1 |
| UIF-04 | Canal live _(built)_ | Live channel delivers an event published on another node. | I CC |
CE, EE | P2 | medium | none |
| UIF-05 | Sélecteur de langue _(built)_ | Language picker switches the page locale. | I |
CE, EE | P3 | easy | none |
| UIF-06 | CSS par route _(built)_ | Per-route CSS injected. | I |
CE, EE | P3 | easy | none |
| UIF-07 | Specs OpenAPI réécrites _(partly built)_ | Rewritten OpenAPI spec served under the route prefix. | U |
CE, EE | P3 | easy | none |
Portal
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| PORTAL-01 | Portail de navigation _(built)_ | Portal bar lists the routes the user may reach. | I |
CE, EE | P3 | easy | none |
| PORTAL-03 | Catalogue d'applications _(built)_ | Application catalogue renders. | I |
CE, EE | P3 | easy | Go 5 |
Identity to the upstream
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| SAUTH-01 | Identité vers l'amont _(partly built)_ | Identity forwarding modes seen by httpbin. | I |
CE, EE | P2 | easy | none |
| SAUTH-02 | Identifiants au coffre _(not built)_ | Not built (send-auth credentials in the vault). | - | CE, EE | - | not built | none |
| SAUTH-03 | Script post-auth _(partly built)_ | Post-auth script not built. | - | CE, EE | - | not built | none |
| SAUTH-04 | Découverte OIDC _(built)_ | The internal plane's /.well-known/openid-configuration names the issuer the tokens carry and a jwks_uri that answers; declaring a public name on the application plane, or choosing among several, changes both the document and the next token, and a typed issuer is refused naming the public addresses. | I |
CE, EE | P2 | easy | none |
| SAUTH-05 | Fournisseur OIDC _(built)_ | OIDC provider: a standard client library (discovery, code + PKCE, then a refresh) signs a person in through a route bound to a declared client and gets RS256 tokens whose claims are the route's and whose issuer and audience it accepts; a person no route grants is refused; with two routes on one client, the first that grants the person decides, and a role removed changes the claims at the next refresh; a client declares no redirect URI (one passed is refused) and gets its code at an address under its route's path, while another route's path, a lookalike prefix, another host or a disabled route's path is refused; the issuer is the application plane's public name, and none declared turns the provider off; a wrong secret, a reused code and a refresh after /logout are refused; the internal plane exchanges a code; on a cluster a code drawn on one node is exchanged on another; the CE image mounts no endpoint and refuses to declare a client. | U I CC |
EE | P1 | medium | Go 1, e2e 1 |
Vault
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| VAULT-01 | Coffre _(built)_ | A $name reference resolves at use, the value never travels back. | I C1 |
CE, EE | P1 | easy | none |
| VAULT-02 | Rotation de la clé _(built)_ | Master key rotation with MEERKAT_VAULT_KEY_PREVIOUS: restart, everything re-sealed, old key removable; rolling across cluster nodes. | C1 CC K1 |
CE, EE | P0 | medium | none |
| VAULT-03 | Coffre portable _(built)_ | Portable vault export/import with its passphrase. | I |
CE, EE | P2 | easy | none |
| VAULT-04 | Coffre externe _(not built)_ | Not built (external vault). | - | CE, EE | - | not built | none |
| VAULT-05 | Champs sensibles _(built)_ | A literal in a sensitive field is refused or moved to the vault. | I |
CE, EE | P2 | easy | Go 1 |
| VAULT-06 | Date de rappel _(built)_ | Reminder date feeds the digest. | U |
CE, EE | P3 | easy | none |
| VAULT-07 | Coffre pour les services _(not built)_ | A service reads a vault value on the internal plane with a token allowed to read it, and each read is in the audit trail. | U |
CE, EE | P3 | hard | none |
TLS
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| SSL-01 | Certificats _(built)_ | Self-signed, PEM import, keystore import, CSR + adopt - each serves on the HTTPS door of the image. | I C1 K1 |
CE, EE | P0 | easy | none |
| SSL-02 | Ports HTTPS _(built)_ | HTTPS doors open on placement and are reachable on the PUBLISHED ports of each target; the TLS screen links match. | C1 S1 K1 |
CE, EE | P0 | easy | none |
| SSL-03 | Secrets TLS _(built)_ | TLS secrets via the vault. | U |
CE, EE | P3 | easy | none |
| SSL-04 | Alerte d'expiration _(built)_ | Expiry digest names a certificate inside its window (clock injected) in the mail sink. | I C1 |
CE, EE | P2 | easy | Go 1 |
| SSL-05 | ACME _(built)_ | ACME against Pebble on the platform network: authority saved, order placed -> issued over TLS-ALPN, renewed; in a cluster issued ONCE (lock); CE refuses. | C1 CC K1 |
EE | P1 | medium | Go 2 |
| SSL-06 | Redirection HTTPS _(built)_ | Force HTTPS redirects only names a certificate carries; a service calling by cluster name stays plain; HSTS only on 443. | I C1 |
CE, EE | P1 | easy | Go 2 |
| SSL-07 | HTTP/3 _(not built)_ | Not built (HTTP/3). | - | CE, EE | - | not built | none |
| SSL-08 | Réserve et placement _(built)_ | Placement on a plane reloads the door on every node; conflict named; fallback = oldest placed. | I CC |
CE, EE | P1 | easy | none |
| SSL-09 | Autorités de confiance _(built)_ | An upstream in HTTPS signed by a private authority is a 502 until that authority is imported - chosen, dropped as a file or pasted - then answers on every node; a private key is refused. On a cluster with cert-manager, From the cluster lists its CA issuer whatever its name, takes its certificate through a throwaway Certificate deleted afterwards, and the issuer's own Secret is never read; a chart without trustDiscovery says which value is missing. Each authority lists the routes in https it signs (a refused one picks it in advance) and the services cert-manager records it signed; once taken, a route in http whose service answers in https on another port is offered with that port. | I CC |
CE, EE | P1 | easy | none |
| SSL-10 | Certificat client vers l'amont _(not built)_ | An upstream that requires a client certificate accepts the route's, and refuses the same call without it. | I |
CE, EE | P3 | medium | none |
| SSL-11 | Certificat depuis le système de fichiers _(built)_ | A TLS Secret mounted in the pod is offered from the mount table with its key, taken by its paths only, and a renewal written into the Secret is served on every node without a restart. | CC |
CE, EE | P1 | medium | none |
| SSL-12 | HTTPS du plan interne _(built)_ | A certificate placed on the internal plane opens :7443; a service trusting its authority reaches the JWKS and the discovery document over HTTPS, whose jwks_uri is https. | CC |
CE, EE | P1 | medium | none |
| SSL-13 | Certificat interne demandé à cert-manager _(built)_ | With internalTls.certManager, the gateway lists the ready issuers, creates its Certificate for its internal names, serves the Secret on :7443 without a mount or a restart, follows a renewal on every node, and deleting it removes the Certificate and the Secret; on Swarm or compose the entry is greyed with its reason. | CC |
CE, EE | P2 | medium | none |
| SSL-14 | Plans, noms et proxy _(built)_ | Each plan is listed by its runtime names with its own certificates. This gateway: a declared public name with no covering certificate is refused, a covered one is served. A proxy in front: a certificate on the plan's internal names lets the proxy re-encrypt (an Ingress with backend HTTPS reaches the console and the application), the declared names are served https without trusting a header, and X-Forwarded-For is believed from the declared proxy addresses only. A plan with no proxy ignores every X-Forwarded header. A wildcard name is refused. The first application name is the one mailed links carry. | U I K1 C1 |
CE, EE | P1 | medium | Go 3, e2e 1 |
| SSL-15 | Porte HTTP par plan _(built)_ | Each plane switches its HTTP door on or off; HTTPS opens with a certificate and closes with the last one. HTTP off listens on 127.0.0.1 only: unreachable from the network, still answering a port-forward and the in-container health check (the pods stay ready). HTTP goes off only while HTTPS serves, and a plane's last certificate stays while its HTTP is off. On the console the door in use is kept: HTTP off is refused while the session or a proxy uses HTTP, the last certificate while they use HTTPS; with an Ingress moved to the HTTPS port, HTTP goes off and the console stays reachable. The console's traffic per door is shown live, pooled across replicas. | U I K1 |
CE, EE | P1 | medium | Go 3, e2e 1 |
Notifications
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| NOTIF-01 | SMTP _(built)_ | SMTP relay test mail arrives in the sink (STARTTLS and plain). | I C1 |
CE, EE | P1 | easy | none |
| NOTIF-02 | Web Push _(not built)_ | Not built (Web Push). | - | CE, EE | - | not built | none |
| NOTIF-03 | Canal WebSocket _(built)_ | WebSocket channel events reach a client connected to another node. | CC |
CE, EE | P2 | medium | none |
| NOTIF-04 | Résumé des expirations _(built)_ | Daily digest sent ONCE per day across a cluster (advisory lock), at the configured hour. | CC |
CE, EE | P1 | medium | none |
| NOTIF-05 | Notifier des utilisateurs _(not built)_ | Not built (notify users by organisation, group, role or user). | - | CE | - | not built | none |
Scheduled calls
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| SCHED-01 | Appels planifiés _(built)_ | A scheduled call fires once per tick across all nodes, against httpbin. | I CC |
CE, EE | P1 | medium | Go 2, e2e 2 |
| SCHED-02 | Tâche ponctuelle _(built)_ | A one-off task fires once. | I |
CE, EE | P2 | easy | Go 3 |
| SCHED-03 | Historique des exécutions _(built)_ | Run history lists runs and replays one. | I |
CE, EE | P3 | easy | Go 3, e2e 2 |
| SCHED-04 | Reprise automatique _(built)_ | Retry bounded on a failing upstream. | I |
CE, EE | P2 | medium | none |
| SCHED-05 | Report demandé par le service _(built)_ | Service-requested delay honoured. | U |
CE, EE | P3 | easy | Go 2 |
Languages
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| I18N-01 | Pages traduites _(built)_ | Sign-in pages served in each of the 20 languages from Accept-Language, no key left untranslated. | I |
CE, EE | P2 | easy | none |
| I18N-02 | Erreurs traduites _(built)_ | Backend errors localised. | U |
CE, EE | P3 | easy | none |
| I18N-03 | Console en anglais _(built)_ | Decision (console in English), nothing to test. | - | CE, EE | - | nothing to test | none |
| I18N-04 | Langues déclarées par route _(built)_ | A route serves only the languages it declares. | I |
CE, EE | P3 | easy | Go 3 |
| I18N-05 | Corriger et ajouter une langue _(built)_ | A language override in the store wins over the embedded catalogue. | I |
CE, EE | P3 | easy | none |
Themes
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| THEME-01 | Thème global _(built)_ | Global theme applied to the sign-in pages. | I |
CE, EE | P3 | easy | none |
| THEME-02 | Marque _(built)_ | Branding applied; hiding the mark refused on CE. | I |
CE, EE | P2 | easy | Go 1 |
| THEME-03 | Palette partagée _(built)_ | Shared palette used by pages and console. | I |
CE, EE | P3 | easy | none |
| THEME-04 | Éditeur M3 _(built)_ | A theme made from six source colours and a contrast level is saved with the schemes Material Theme Builder makes of them, and the pages use it. | I |
CE, EE | P3 | easy | Go 1 |
| THEME-05 | Clair / sombre _(built)_ | Light/dark follows the user choice. | I |
CE, EE | P3 | easy | Go 1 |
| THEME-08 | Un thème se nomme _(built)_ | A named theme selectable. | I |
CE, EE | P3 | easy | none |
| THEME-07 | Apercu de tous les gabarits _(built)_ | Template previews render with their data set. | I |
CE, EE | P3 | easy | none |
| THEME-06 | Fond de marque _(built)_ | Brand background rendered. | I |
CE, EE | P3 | easy | Go 2 |
| THEME-09 | Polices du thème _(built)_ | A theme's fonts are served by the gateway itself and set the pages, nothing fetched from a CDN. | I |
CE, EE | P3 | easy | none |
Console
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| CONSOLE-01 | Console d'administration _(built)_ | The console loads from the image on the admin port of each target and signs in. | I C1 K1 |
CE, EE | P0 | easy | none |
| CONSOLE-02 | Menus par droits _(built)_ | Menus follow the rights of each profile (console-nav). | I |
CE, EE | P1 | easy | none |
| CONSOLE-03 | Éditeur de route _(built)_ | Route editor saves every section and the route serves. | I |
CE, EE | P2 | easy | none |
| CONSOLE-04 | Sécurité des endpoints _(partly built)_ | Endpoint security screen edits rules that apply. | I |
CE, EE | P2 | easy | none |
| CONSOLE-05 | Export / import _(built)_ | Export a file from CE and import it into EE and back; the plan names what CE leaves out. | I C1 |
CE, EE | P1 | easy | none |
| CONSOLE-06 | Réglages _(partly built)_ | Settings screens save. | I |
CE, EE | P3 | easy | none |
| CONSOLE-07 | Utilisateurs _(partly built)_ | Users screen: create, temporary password, reset. | I |
CE, EE | P2 | easy | Go 1 |
| CONSOLE-08 | Connexions et sessions _(built)_ | Sessions screen scoped per admin perimeter. | I |
CE, EE | P2 | easy | Go 1, e2e 1 |
| CONSOLE-09 | Profil _(partly built)_ | Profile edits saved. | I |
CE, EE | P3 | easy | none |
| CONSOLE-10 | Suppression de compte _(partly built)_ | Account deletion revokes sessions. | I |
CE, EE | P3 | easy | none |
| CONSOLE-11 | Console à part _(built)_ | Console on its own port, never on the data plane (data port answers no /api). | C1 K1 |
CE, EE | P1 | easy | none |
| CONSOLE-12 | Écran des routes _(built)_ | Routes screen reorders and toggles. | I |
CE, EE | P3 | easy | none |
| CONSOLE-13 | Écrans vivants _(partly built)_ | A change made on node A refreshes a console open on node B. | CC |
CE, EE | P2 | medium | Go 1 |
| CONSOLE-14 | Ce que l'édition Enterprise apporte _(built)_ | License page lists the EE features, locked on CE. | I |
CE, EE | P2 | easy | e2e 1 |
| CONSOLE-15 | Version et notes de version _(built)_ | Version and release notes match the image's stamped version. | C1 |
CE, EE | P2 | easy | none |
Lifecycle
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| LIFE-01 | Premier démarrage _(built)_ | First start of each image on each target: admin bootstrap from env, readiness green, no route open. | C1 S1 K1 KO |
CE, EE | P0 | easy | none |
| LIFE-02 | Seed déclaratif _(built)_ | Declarative seed from a mounted file (ConfigMap / compose volume) applied once. | C1 K1 |
CE, EE | P1 | easy | Go 1 |
| LIFE-03 | Mode développeur _(built)_ | Developer mode switch gates dev features. | I |
CE, EE | P3 | easy | none |
| LIFE-04 | Doc d'API _(built)_ | API docs pages served. | I |
CE, EE | P3 | easy | none |
| LIFE-05 | Indisponibilité _(built)_ | A route in maintenance answers its unavailable page (503). | I |
CE, EE | P2 | easy | Go 1, e2e 1 |
Developer tunnel
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| DEV-01 | Capacité dev _(built)_ | Dev capability gates dev screens. | I |
CE, EE | P3 | easy | Go 1 |
| DEV-02 | Clés de développeur _(built)_ | Developer key deposited and revoked. | I |
EE | P2 | easy | none |
| DEV-03 | Poste vers cluster _(partly built)_ | plug: workstation reaches a cluster service through the gateway tunnel (reuse plug's e2e cells). | S1 K1 |
EE | P2 | hard | none |
| DEV-04 | Cluster vers poste _(partly built)_ | plug: a cluster service is substituted by a local process and restored on exit. | S1 K1 |
EE | P2 | hard | none |
| DEV-05 | Portée des substitutions _(retired)_ | Retired (one instance of a service runs at a time). | - | CE, EE | - | nothing to test | none |
| DEV-06 | Annonce aux utilisateurs _(built)_ | Users are told a substitution is active. | I |
EE | P3 | easy | none |
| DEV-07 | Cycle de vie _(partly built)_ | Substitution removed when the developer disconnects. | K1 |
EE | P3 | hard | none |
| DEV-08 | Substitutions simultanées _(partly built)_ | Two developers on two names. | K1 |
EE | P3 | hard | none |
| DEV-09 | Outillage de test _(partly built)_ | Test tooling endpoints answer. | I |
CE, EE | P3 | easy | none |
| DEV-10 | Mode test UI _(built)_ | UI test mode. | I |
CE, EE | P3 | easy | Go 1 |
| DEV-11 | Cadre de sécurité _(partly built)_ | Tunnel security frame enforced. | K1 |
EE | P3 | medium | e2e 1 |
| DEV-12 | Console en dev _(built)_ | Console in dev mode. | I |
CE, EE | P3 | easy | none |
| DEV-13 | Sessions plug _(built)_ | A plug run on several replicas is one row; ending it stops the developer's command and restores the parked service on every node. | K1 |
EE | P2 | medium | e2e 1 |
| DEV-14 | Audit du tunnel _(partly built)_ | A session's opening and end, and each name served, are written to the trail once, whatever the number of replicas. | K1 |
EE | P2 | medium | none |
Configurations
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| CFG-01 | Collection _(built)_ | Saved configurations listed, CE capped at three. | I |
CE, EE | P2 | easy | Go 3 |
| CFG-02 | Configuration active _(built)_ | Set as current applies on every node. | I CC |
CE, EE | P1 | easy | e2e 1 |
| CFG-03 | Fichier au démarrage _(built)_ | A configuration file at first start becomes the active one (mounted file). | C1 K1 |
CE, EE | P1 | easy | Go 1 |
| CFG-04 | Comparaison _(built)_ | Compare shows added/removed/changed. | I |
CE, EE | P3 | easy | Go 1, e2e 1 |
| CFG-05 | Export _(built)_ | Export round-trips (ZIP with assets). | I |
CE, EE | P2 | easy | Go 1 |
| CFG-06 | Points de reprise _(built)_ | Restore points: restore one, state matches. | I |
CE, EE | P2 | easy | Go 2 |
| CFG-07 | Dépôt git _(built)_ | Git locations against a Gitea on the platform: pull replaces, push replaces only the directory, two platforms share a repo; CE refuses. | C1 CC |
EE | P1 | medium | Go 2, e2e 1 |
Pages
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| PAGE-01 | Pages vanilla _(partly built)_ | Vanilla pages render without JS errors. | I |
CE, EE | P3 | easy | none |
| PAGE-02 | Layouts _(partly built)_ | Layouts selectable on EE, centred only on CE. | I |
CE, EE | P3 | easy | none |
| PAGE-03 | Traductions surchargeables _(built)_ | Overridden translations shown. | I |
CE, EE | P3 | easy | none |
| PAGE-04 | Web Components _(partly built)_ | Web components load. | I |
CE, EE | P3 | easy | none |
| PAGE-05 | Console embarquée _(built)_ | Embedded console served. | I |
CE, EE | P3 | easy | none |
| PAGE-06 | Layout de la console _(partly built)_ | Console layout. | I |
CE, EE | P3 | easy | none |
| PAGE-07 | Composants softwarity _(built)_ | Softwarity components render. | I |
CE, EE | P3 | easy | none |
Quotas
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| QUOTA-01 | Quotas _(partly built)_ | Quotas count per caller (route, user, token, organisation, address), per node (sharing them across nodes is QUOTA-04). | U I |
CE, EE | P2 | medium | none |
| QUOTA-02 | Réponse 429 _(partly built)_ | 429 carries Retry-After. | I |
CE, EE | P2 | easy | none |
| QUOTA-03 | Consommation _(not built)_ | Not built (consumption). | - | CE, EE | - | not built | none |
| QUOTA-04 | Compteurs en cluster _(not built)_ | Not built (cluster quota counters). | - | CE, EE | - | not built | none |
| QUOTA-05 | Quotas par endpoint _(built)_ | Per-endpoint quota refuses one operation, not its neighbour. | I |
CE, EE | P2 | easy | Go 1 |
Audit
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| AUD-01 | Journal d'audit _(partly built)_ | Every admin mutation appears in the trail with actor and diff, whichever node took it. | I CC |
CE, EE | P1 | easy | none |
| AUD-02 | Rétention et export _(built)_ | Retention purges old events; CSV export (EE) refused on CE. | I |
CE, EE | P2 | easy | Go 1, e2e 1 |
| AUD-03 | L'audit vers OpenTelemetry _(built)_ | Audit events reach an OpenTelemetry Collector on the platform (file exporter checked). | C1 |
EE | P2 | medium | Go 1 |
| AUD-04 | Audit des endpoints _(partly built)_ | Endpoint audit records chosen operations to the collector; CE keeps rules unapplied. | C1 |
EE | P2 | medium | Go 4 |
Issues
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| ISSUE-01 | Signalement _(built)_ | An issue filed from a page lands in the console. | I |
CE, EE | P3 | easy | none |
| ISSUE-02 | Stockage _(built)_ | Issue screenshots stored. | U |
CE, EE | P3 | easy | none |
| ISSUE-03 | Suivi en console _(built)_ | Issue follow-up in the console. | I |
CE, EE | P3 | easy | e2e 1 |
| ISSUE-04 | Interrupteur _(built)_ | Issue switch hides the button. | I |
CE, EE | P3 | easy | e2e 1 |
| ISSUE-05 | Connecteurs _(not built)_ | Not built (connectors). | - | CE, EE | - | not built | none |
| ISSUE-06 | Annotations _(not built)_ | Not built (numbered annotations). | - | CE, EE | - | not built | none |
Agents (MCP)
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| MCP-01 | Serveur MCP _(built)_ | MCP endpoint answers initialize and tools/list through the image with an agent token. | I C1 |
CE, EE | P1 | easy | Go 1, e2e 1 |
| MCP-02 | Jeton d'agent _(built)_ | Agent token scope: read-only token refused on writes. | I |
CE, EE | P2 | easy | Go 2 |
| MCP-03 | Acteur audité _(built)_ | Agent actions audited under the token's account. | I |
CE, EE | P2 | easy | Go 1 |
| MCP-04 | Outils métier _(built)_ | Business tools round-trip (save_route, list_routes). | I |
CE, EE | P2 | easy | Go 1 |
| MCP-05 | Écriture directe, et le filet _(built)_ | Direct write plus restore point. | I |
CE, EE | P2 | easy | none |
| MCP-07 | Branchement OAuth _(built)_ | OAuth plug-in flow for an MCP client. | I |
CE, EE | P3 | medium | Go 2, e2e 1 |
| MCP-06 | Export ET import pour l'agent _(built)_ | Export/import tools for the agent. | I |
CE, EE | P3 | easy | none |
| MCP-08 | Appeler les services _(built)_ | An agent lists a route's operations and calls one through the gateway: 200 with every role, 403 naming the missing role without it, the service's own refusal passed through, every call audited. | U I |
CE, EE | P2 | easy | Go 1 |
| MCP-09 | Tout le plan de contrôle _(built)_ | An agent creates an organisation and edits a theme through call_admin_api: the endpoint's guard decides (403 for an account that administers nothing), a read-only token is refused a write, the trail names the token; a closed endpoint (the vault, the TLS doors) is refused with its reason, and a document changing the TLS setting is refused to an agent whichever way it is applied. | U I |
CE, EE | P2 | easy | Go 1 |
Security
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| SEC-01 | CSRF _(partly built)_ | Cross-site form posts refused (Origin/SameSite). | I |
CE, EE | P1 | easy | Go 1 |
| SEC-02 | CORS _(partly built)_ | CORS answers only the configured origin. | I |
CE, EE | P2 | easy | none |
| SEC-03 | En-têtes de sécurité _(built)_ | Security headers present on pages and console from the image. | I C1 |
CE, EE | P1 | easy | none |
| SEC-04 | Aucun secret en clair _(built)_ | No secret in clear: grep a DB dump and the logs for passwords, TOTP secrets, private keys, tokens. | C1 K1 |
CE, EE | P0 | easy | Go 1 |
| SEC-05 | Hachage _(built)_ | Password hashing parameters. | U |
CE, EE | P3 | easy | Go 1 |
| SEC-06 | Chiffrement au repos _(built)_ | Encryption at rest: sealed columns unreadable without the vault key; a node with another key says so. | C1 K1 |
CE, EE | P1 | medium | Go 2 |
| SEC-07 | Révocation _(built)_ | Revoking a session or token takes effect on every node at once. | I CC |
CE, EE | P1 | easy | Go 2, e2e 1 |
| SEC-08 | Audit _(partly built)_ | Security events in the trail. | I |
CE, EE | P3 | easy | none |
| SEC-09 | Anti-énumération _(built)_ | Sign-in and forgotten password answer the same for known and unknown accounts (timing within bounds). | I |
CE, EE | P2 | easy | none |
| SEC-10 | Rien de personnel en cache _(built)_ | No personal page cached (Cache-Control: no-store). | I |
CE, EE | P2 | easy | none |
| SEC-11 | Proxies de confiance _(built)_ | A caller reaching the gateway directly cannot choose its address: a rotating X-Forwarded-For from a public peer still ends in 429, the same header from the Ingress is believed when the plane declares a proxy in front, a plane served by the gateway itself ignores it, and a public peer's X-Forwarded-Proto does not skip the https redirect. | I |
CE, EE | P1 | easy | none |
Performance and cluster
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| PERF-01 | Non bloquant _(built)_ | A slow upstream does not slow the others (concurrent load). | C1 |
CE, EE | P2 | medium | none |
| PERF-05 | Bancs de mesure _(built)_ | Benchmarks published per arch (existing CI). | U |
CE, EE | P2 | easy | none |
| PERF-02 | Streaming _(built)_ | Streaming: a large download and an SSE stream pass without buffering (memory flat). | I C1 |
CE, EE | P1 | easy | e2e 1 |
| PERF-03 | Cluster actif/actif _(built)_ | Active/active: two or three gateways on one PostgreSQL behind a load balancer; any node serves any session. | CC SC KC |
EE | P0 | medium | none |
| PERF-04 | État partagé _(built)_ | Shared state: sessions, rate limits, locks, change bus across nodes. | CC |
EE | P0 | medium | none |
| PERF-06 | Validateur sur une page réécrite _(built)_ | Validator on a rewritten page. | U |
CE, EE | P3 | easy | Go 2 |
Observability
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| OBS-01 | Tableau de bord _(built)_ | Traffic dashboard sums every node of a cluster. | I CC |
CE, EE | P2 | easy | e2e 1 |
| OBS-02 | Health checks _(built)_ | Liveness/readiness/startup probes as the chart and compose use them; readiness drops while migrating. | C1 K1 KO |
CE, EE | P0 | easy | none |
| OBS-03 | Logs _(built)_ | Log level change propagated to all nodes and reverted after 30 minutes (clock injected). | I CC |
CE, EE | P2 | easy | Go 2, e2e 1 |
| OBS-04 | Tracing _(partly built)_ | traceparent reaches the upstream in both editions; spans exported to the collector in EE only. | C1 |
CE, EE | P2 | medium | Go 4, e2e 1 |
| OBS-05 | Prometheus _(retired)_ | Retired (the Collector does it). | - | EE | - | nothing to test | none |
| OBS-06 | Une seule adresse : le Collector _(built)_ | Metrics and logs pushed over OTLP to the collector. | C1 |
EE | P2 | medium | none |
Deployment
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| DEPLOY-01 | Image unique _(built)_ | One image per edition runs unchanged on compose, swarm and kind; edition reported matches. | C1 S1 K1 KO |
CE, EE | P0 | easy | none |
| DEPLOY-02 | Variables d'environnement _(built)_ | Every documented environment variable has its effect (table-driven from the docs). | C1 K1 |
CE, EE | P1 | easy | none |
| DEPLOY-03 | Zéro dépendance _(built)_ | Runs with no external dependency (SQLite, no network egress). | C1 |
CE, EE | P0 | easy | none |
| DEPLOY-04 | CI/CD _(built)_ | CI itself (this plan's runner). | - | CE, EE | P2 | easy | none |
| DEPLOY-05 | Éditions _(partly built)_ | Edition truth: the CE image refuses every EE endpoint and locks every EE control; the EE image allows them. | I C1 |
CE, EE | P0 | easy | none |
| DEPLOY-06 | Migrations _(partly built)_ | Upgrade from the previous release on SQLite and PostgreSQL: migrations run, data kept, rollback to the older binary refused cleanly. | C1 CC K1 |
CE, EE | P0 | medium | none |
| DEPLOY-07 | Fichiers de déploiement _(built)_ | The published files (docker-compose.yml, .ee.yml, stack.swarm.yml, helm values) deploy as shipped - the platform uses THEM, rewritten only for the image tag (asserted). | C1 S1 K1 CC KC KO |
CE, EE | P0 | easy | none |
| DEPLOY-08 | Images signées _(partly built)_ | cosign verify succeeds on the image under test with the workflow's identity, for the digest and for each architecture; an unsigned or re-pushed image fails. | C1 |
CE, EE | P1 | easy | none |
| DEPLOY-09 | Plan interne _(built)_ | The internal plane answers the JWKS without a token and the scheduler API with a schedules token only, refuses a browser session, and the chart publishes it on a ClusterIP Service nothing else points at; the application port serves no JWKS. | I CC |
CE, EE | P1 | easy | none |
Storage
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| STORE-01 | Autonome _(built)_ | Standalone on SQLite in a volume; restart keeps everything. | C1 |
CE, EE | P1 | easy | none |
| STORE-02 | SQLite ou PostgreSQL _(built)_ | Same suite on PostgreSQL (existing CI job) and through the image. | CC KC |
CE, EE | P0 | easy | none |
| STORE-07 | Montée de version _(partly built)_ | A database seeded by the previous release opens with this one (fixture DB per release). | C1 CC |
CE, EE | P0 | medium | none |
| STORE-03 | Cluster _(built)_ | Cluster store: two nodes, one database, no split brain on locks. | CC KC |
EE | P0 | medium | none |
| STORE-04 | Tout dans la base _(built)_ | Nothing stored on local disk besides /data (read-only rootfs works with an emptyDir on /tmp, snapshot download included). | C1 |
CE, EE | P2 | easy | none |
| STORE-08 | Écriture périmée refusée _(built)_ | A stale write answers 409 and the console offers reload. | U I |
CE, EE | P2 | easy | none |
| STORE-05 | Sauvegarde _(partly built)_ | Backup snapshot downloaded and restored by the documented procedure. | C1 KO |
CE, EE | P1 | medium | none |
| STORE-06 | Export du journal _(partly built)_ | Audit trail export (CSV). | I |
EE | P3 | easy | Go 1, e2e 1 |
Quality
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| QUAL-01 | Tests _(built)_ | This plan. | - | CE, EE | - | nothing to test | e2e 1 |
| QUAL-02 | Documentation _(built)_ | Docs links and screenshots checked (screenshots.mjs --check). | - | CE, EE | P3 | easy | none |
EVAL
| ID | Feature | What has to be proved | Targets | Editions | Priority | Feasibility | Tests naming it today |
|---|---|---|---|---|---|---|---|
| EVAL-01 | Image d'évaluation _(built)_ | The evaluation image reports edition eval at startup, serves every Enterprise feature the EE image serves, and never stops the data plane: the same smoke chain passes on day one and with the clock moved a year forward. | C1 |
EVAL | P1 | easy | none |
| EVAL-02 | Mention sur les pages du flux _(built)_ | Every built-in page carries the evaluation notice, in each locale, and it survives a brand configured to hide the mark; the EE image shows none of it. | I C1 |
EVAL | P1 | easy | none |
| EVAL-03 | Mention dans le bouton utilisateur et les e-mails _(built)_ | The user button injected into a proxied page carries the notice when opened, through gzip and brotli, and a response over the rewrite ceiling still arrives whole. | I |
EVAL | P2 | easy | none |
| EVAL-04 | Filigrane de la console _(built)_ | The console shows the evaluation watermark on a dense screen in both colour schemes, behind the content, and every row stays clickable. | I |
EVAL | P2 | easy | none |
| EVAL-05 | Les tables laissent passer le fond _(partly built)_ | No card, table or row of the console paints an opaque background over the page; the sticky header and the frozen columns are the two stated exceptions, and every banded table hovers the same colour. | I |
CE, EE, EVAL | P2 | easy | none |