diff --git a/.gitignore b/.gitignore
index ca0cce9..2d268c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,3 +55,28 @@ jspm_packages
/dist_keycloak
/build
/storybook-static
+
+# ── Secrets and credentials ───────────────────────────────────────────────
+# Deliberately explicit. Nothing sensitive has ever been committed here (634
+# commits scanned before this repo went public: no .env, no key material, no
+# credentials), and these patterns are what keeps that true.
+#
+# Real configuration lives in the .env file on the deploy host and in GitHub
+# environment secrets. Neither belongs in git.
+.env
+.env.*
+!.env.example
+*.pem
+*.key
+*.p12
+*.keystore
+id_rsa
+id_ed25519
+
+# ── Python (tooling that runs alongside this repo) ────────────────────────
+__pycache__/
+*.py[cod]
+.pytest_cache/
+.ipynb_checkpoints/
+coverage.xml
+.coverage
diff --git a/README.md b/README.md
index 4690a23..1151edf 100644
--- a/README.md
+++ b/README.md
@@ -1,59 +1,131 @@
-
- 🚀 Keycloakify v11 starter 🚀
-
-
-
+# CivicDataLab Keycloak Theme
-# Quick start
+[](https://github.com/CivicDataLab/DataSpaceKeycloakTheme/actions/workflows/deploy-keycloak-staging.yml)
+[](https://github.com/CivicDataLab/DataSpaceKeycloakTheme/actions/workflows/ci.yaml)
+[](https://www.keycloak.org/)
+[](https://keycloakify.dev)
-```bash
-git clone https://github.com/CivicDataLab/DataSpaceKeycloakTheme
-cd DataSpaceKeycloakTheme
-yarn install # Or use an other package manager, just be sure to delete the yarn.lock if you use another package manager.
-yarn storybook
-```
+The login, registration and account pages for
+[**auth.civicdatalab.in**](https://auth.civicdatalab.in) — the identity provider
+every CivicDataLab product authenticates through.
-# Testing the theme locally
+Built with [Keycloakify](https://keycloakify.dev) v11 on Keycloak 26.7.0.
-[Documentation](https://docs.keycloakify.dev/testing-your-theme)
+---
-# How to customize the theme
+## ⚠️ This deploys to production
-[Documentation](https://docs.keycloakify.dev/customization-strategies)
+`auth.civicdatalab.in` is **production**. It serves authentication for:
-# Building the theme
+| Product | Environments |
+|---|---|
+| CivicDataSpace | dev + prod |
+| ParakhAI | dev + prod |
+| Analytics (Superset) | dev + prod |
+| DataSpace behind IDS-DRR | dev + prod |
-You need to have [Maven](https://maven.apache.org/) installed to build the theme (Maven >= 3.1.1, Java >= 7).
-The `mvn` command must be in the $PATH.
+A broken deploy here **signs every user out of every product**. Treat changes
+accordingly.
-- On macOS: `brew install maven`
-- On Debian/Ubuntu: `sudo apt-get install maven`
-- On Windows: `choco install openjdk` and `choco install maven` (Or download from [here](https://maven.apache.org/download.cgi))
+**Merging to `main` deploys immediately.** Work lands on `dev` first; pushing to
+`dev` deploys nothing.
+
+## How a change reaches users
-```bash
-npm run build-keycloak-theme
```
+PR ──► dev ──────────────────────────────► (no deploy)
+ │
+ └─ reviewed, merged to main
+ │
+ ▼
+ Build image ──► push to GHCR (digest-pinned)
+ │
+ ▼
+ Deploy ──► pg_dump backup taken first
+ │
+ ├─ health gate: /health/ready
+ │ └─ unhealthy ──► automatic rollback to the previous image
+ ▼
+ Keycloak tests (CivicDataSpace-test)
+ login page · Google sign-in · privacy links · issuer
+```
+
+The tests run from
+[`CivicDataSpace-test`](https://github.com/CivicDataLab/CivicDataSpace-test)
+after every deploy, because the theme ships independently of the applications —
+a theme change can break sign-in while every product's own pipeline stays green.
-Note that by default Keycloakify generates multiple .jar files for different versions of Keycloak.
-You can customize this behavior, see documentation [here](https://docs.keycloakify.dev/features/compiler-options/keycloakversiontargets).
+### The rollback is not a complete safety net
-# Initializing the account theme
+A Keycloak **major** upgrade migrates the database schema via Liquibase, and that
+is one-way. Rolling the image back does **not** undo it, and the older image
+cannot start against the new schema. Every deploy takes a `pg_dump` first for
+exactly this reason; restore it before retrying an older image.
+
+## Local development
```bash
-npx keycloakify initialize-account-theme
+git clone https://github.com/CivicDataLab/DataSpaceKeycloakTheme
+cd DataSpaceKeycloakTheme
+npm install
+npm run storybook # every page, no Keycloak needed
```
-# Initializing the email theme
+Storybook is the fastest loop: each page has a story, including error and
+validation states that are awkward to reproduce against a live server.
+
+To test against a real Keycloak, see the
+[Keycloakify testing guide](https://docs.keycloakify.dev/testing-your-theme).
+
+### Building the theme jar
+
+Requires Maven ≥ 3.1.1 and a JDK on `$PATH`.
```bash
-npx keycloakify initialize-email-theme
+npm run build-keycloak-theme
```
-# GitHub Actions
+Keycloakify emits **one jar per Keycloak version range**. This deployment uses
+`keycloak-theme-for-kc-all-other-versions.jar` — the one for Keycloak 26+. The
+other jar, `keycloak-theme-for-kc-22-to-25.jar`, bundles a password-policy
+extension that 22–25 needed and 26 provides natively. Copying both into
+`providers/` lets Keycloak pick a theme you did not intend.
+
+## Customising
+
+- [Customization strategies](https://docs.keycloakify.dev/customization-strategies)
+- `npx keycloakify initialize-account-theme` — account pages
+- `npx keycloakify initialize-email-theme` — email templates
+
+## Names that must not be changed
+
+Several identifiers still say "staging" for historical reasons. They are
+cosmetic, and renaming any of them causes an outage:
+
+| Identifier | Renaming it |
+|---|---|
+| `CONTAINER_NAME` (`keycloak-staging`, `keycloak-staging-db`) | compose creates a **second** container and orphans the running one |
+| volume `kc_postgres_data` | Keycloak gets an **empty database** — every realm, client and user lost |
+| `DEPLOY_PATH` | the deploy targets a directory that does not exist |
+
+Each site carries a comment in the workflow saying so. Please leave them.
+
+## Configuration and secrets
+
+No credentials live in this repository, and none ever have. Runtime
+configuration is an environment file on the deployment host; deploy credentials
+are GitHub **environment** secrets on `keycloak-production`. The compose file
+references variables such as `${KEYCLOAK_PASSWORD}` and never their values.
+
+Note that `${KC_BOOTSTRAP_ADMIN_*}` are the Keycloak 26 variable names. On
+Keycloak 24 they were silently ignored — `kc.sh show-config` echoed them back,
+which is what made them look like they worked.
+
+## Reporting a security issue
+
+See [SECURITY.md](SECURITY.md). Please do not open a public issue for a
+vulnerability in an authentication surface.
-The starter comes with a generic GitHub Actions workflow that builds the theme and publishes
-the jars [as GitHub releases artifacts](https://github.com/keycloakify/keycloakify-starter/releases/tag/v10.0.0).
-To release a new version **just update the `package.json` version and push**.
+## Licence
-To enable the workflow go to your fork of this repository on GitHub then navigate to:
-`Settings` > `Actions` > `Workflow permissions`, select `Read and write permissions`.
+See [LICENSE](LICENSE).
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..beed0b8
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,61 @@
+# Security Policy
+
+This repository contains the Keycloakify theme for CivicDataLab's identity
+provider. Because it renders the login, registration and account pages that
+every CivicDataLab product authenticates through, security reports here are
+treated with priority.
+
+## Reporting a vulnerability
+
+**Please do not open a public issue for a security problem.**
+
+Report privately, whichever is easier:
+
+- **GitHub** — the *Security* tab → *Report a vulnerability* (private advisory).
+ Preferred, because the discussion stays attached to this repository.
+- **Email** — [info@civicdatalab.in](mailto:info@civicdatalab.in) with
+ `SECURITY` in the subject line.
+
+Helpful to include, though a partial report is far better than none:
+
+- what an attacker could achieve, not only what is technically wrong
+- the steps to reproduce it, and the affected page or endpoint
+- the browser and version, if the issue is a rendering or client-side one
+- whether you believe it is already being exploited
+
+We aim to acknowledge within **five working days**. CivicDataLab is a small
+team, so please allow reasonable time for a fix before disclosing publicly. We
+are glad to credit reporters in the advisory unless you prefer otherwise.
+
+## Scope
+
+**In scope** — anything in this repository: the theme's page templates,
+components and build configuration, and the deployment workflow under
+`.github/workflows/`.
+
+**Out of scope, but still worth telling us about** — issues in the products
+that use this theme, or in the identity provider's own configuration. Those are
+not fixed by changes here, but the same contacts will route them.
+
+**Not in scope** — findings against Keycloak or Keycloakify themselves. Report
+those upstream:
+
+- Keycloak: https://github.com/keycloak/keycloak/security
+- Keycloakify: https://github.com/keycloakify/keycloakify
+
+## A note on what is in this repository
+
+There are no credentials here, and there never have been. Runtime configuration
+lives in an environment file on the deployment host and in GitHub environment
+secrets; the compose file references variables such as `${KEYCLOAK_PASSWORD}`
+and never their values. The history was scanned across all 634 commits before
+this repository was made public.
+
+If you do find committed key material, that is itself the vulnerability and we
+would like to know urgently.
+
+## What a report will not be penalised for
+
+Reports made in good faith are welcome even if they turn out to be a false
+positive or already known. We would rather read a duplicate than miss a real
+issue because someone hesitated.