Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ truth** for permissions, querysets, forms, and field configuration — both
packages honour that contract.

> This document is the architectural contract for the **SPA super-layer**.
> Any change that conflicts with it must update this file in the same PR
> and be recorded in [`docs/agents/decisions.md`](docs/agents/decisions.md).
> The wire-contract document (what the API actually emits / accepts) lives
> in the **API repo** — this file refers to it but does not duplicate it.

Expand Down Expand Up @@ -216,8 +214,7 @@ Conservative, list in [`SECURITY.md`](SECURITY.md) and codified in
with timezone).
- `ForeignKey` → `{ "id": ..., "label": str(obj) }`.
- `ManyToMany` → list of `{ "id": ..., "label": str(obj) }` envelopes
(Issue #55; supersedes the earlier "unsupported" decision logged in
`docs/agents/decisions.md`).
(Issue #55).
- `FileField` / `ImageField` → `{ "name", "url", "size" }`; `url` defers
to the consumer's storage backend so signed-URL backends work
unchanged (Issue #57).
Expand Down Expand Up @@ -377,8 +374,7 @@ There is exactly one data path inside the SPA:

- The package ships a `tailwind.config.js` with a minimal, modern, neutral
palette and CSS-variable-backed colors for trivial recoloring.
- Consumers can extend it via their own `tailwind.config.js`; this is
documented in `docs/installation.md`.
- Consumers can extend it via their own `tailwind.config.js`.
- **Partial replacement is supported** (e.g., override `colors`, `fontFamily`,
`spacing`).
- **Full replacement of the config is not a v1 goal** — it would mean every
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,9 @@ register_field_type(MoneyField, vocab_type="decimal")
# code required.
```

For coining a brand-new `vocab_type` (with a matching SPA widget)
see [`docs/extensions.md`](docs/extensions.md).
Coining a brand-new `vocab_type` (with a matching SPA widget) is an
**API-repo** concern — open the issue at
[`MartinCastroAlvarez/django-admin-api`](https://github.com/MartinCastroAlvarez/django-admin-api).

### Pre-built `get_*` overrides still work

Expand Down Expand Up @@ -531,8 +532,9 @@ frontend, a script).

Every endpoint is **staff-only by default** (or whatever
`AdminSite.has_permission` returns), CSRF-required on unsafe
methods, and emits `Cache-Control: no-store`. Full wire contract:
[`docs/api-contract.md`](docs/api-contract.md).
methods, and emits `Cache-Control: no-store`. Full wire contract
lives in the API repo:
[`MartinCastroAlvarez/django-admin-api`](https://github.com/MartinCastroAlvarez/django-admin-api).

---

Expand Down
68 changes: 27 additions & 41 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,9 @@ them must not merge.
`exclude`. The set of readable fields is similarly derived from
`get_fields(request, obj)`/`get_fieldsets(...)`.
7. **Never serialize passwords, tokens, API keys, or other secret-shaped
fields.** A denylist of common patterns lives in
`api/serializers.py` and is applied **on top of** the
`exclude`/`readonly_fields` rules (defense in depth). Documented in
`docs/api-contract.md`.
fields.** A denylist of common patterns lives in the
`django-admin-rest-api` package and is applied **on top of** the
`exclude`/`readonly_fields` rules (defense in depth).
8. **Writes always go through the admin form.** Create and update must
instantiate `ModelAdmin.get_form(request, obj=...)` and call
`form.is_valid()`. No manual `setattr(obj, field, ...)` from JSON.
Expand Down Expand Up @@ -144,22 +143,14 @@ Every endpoint added must include all of these tests before merging:
## 5. Secrets in the repository

- `.env`, `*.pem`, `*.key`, `*.crt`, and `secrets/` are gitignored.
- Never paste a token, password, or API key into any file in this repo
(including `docs/agents/`, PR descriptions, Issues, Discussions, commit
messages). **Partial / redacted token references** (e.g., `ghp_…XYZ`)
are also forbidden and detected by the pre-commit hook +
`tests/test_security.py`.
- If a secret is accidentally committed, the response is:
1. Rotate the secret immediately on the upstream provider.
2. **Wait for human approval** before rewriting history. No agent may
`git push --force` autonomously. Once approved, force-push the
rewritten history that removes the secret and notify downstream
consumers.
3. Open a GitHub Issue labelled `incident:secret-leak` describing what
happened and what was rotated. The Issue itself is the durable
record; an Issue with that label active is a "kill switch" entry
that disables auto-merge per
`docs/agents/autonomy-policy.md` §3.
- Never paste a token, password, or API key into any file in this repo,
PR description, Issue, Discussion, or commit message. **Partial /
redacted token references** (e.g., `ghp_…XYZ`) are also forbidden and
detected by the pre-commit hook.
- If a secret is accidentally committed: (1) rotate it immediately on
the upstream provider; (2) request approval to rewrite history; (3)
open a GitHub Issue labelled `incident:secret-leak` as the durable
record.
- A pre-commit hook (`.pre-commit-config.yaml`) runs `gitleaks` plus a
custom `pygrep` for partial token patterns. Enable it locally with:
`pre-commit install`.
Expand All @@ -176,12 +167,9 @@ Every endpoint added must include all of these tests before merging:
the same.
- Dev dependencies are pinned in `pyproject.toml` and locked with Poetry.
Frontend dev dependencies are locked with `pnpm-lock.yaml`.
- Every new third-party dependency (runtime **or** dev) requires a
matching entry in `docs/agents/decisions.md` explaining why and what
alternative was rejected.
- Run `./scripts/audit-deps.sh` before every release. CI is intentionally
absent (repo-owner direction); the dep audit is a local gate that the
Merger / Releaser owns.
- Every new third-party dependency (runtime **or** dev) goes through PR
review explaining why and what alternative was rejected.
- Run `./scripts/audit-deps.sh` before every release.

## 7. Build & release

Expand All @@ -193,20 +181,17 @@ Every endpoint added must include all of these tests before merging:
- The PyPI token lives in environment variables only
(`POETRY_PYPI_TOKEN_PYPI`), never in any file in the repo. The token
is **never** echoed or logged by `scripts/deploy.sh`.
- Releases require a **human maintainer** (tier 6 in
`docs/agents/autonomy-policy.md`). Agents do not tag, do not publish,
do not auto-bump the version.
- Releases require a **human maintainer**. The publish is driven by the
`release.yml` workflow (OIDC Trusted Publishing — no stored token);
the maintainer triggers it by publishing a GitHub Release.
- TestPyPI may be used for verification by the maintainer with a
separate token; same hygiene rules apply.

## 8. Static analysis (local + CI)

The earlier "local-only, no CI in v0.x" posture was revisited and
reversed (issue #452 — regressions were slipping onto `main` under
CodeQL-only gating; see `docs/agents/decisions.md`). **The test suites
now run server-side in CI** (`.github/workflows/ci.yml`): backend
`pytest` and the frontend `pnpm` gate (typecheck + lint + test + build),
so a red suite cannot merge.
**The test suites run server-side in CI**
(`.github/workflows/ci.yml`): backend `pytest` and the frontend `pnpm`
gate (typecheck + lint + test + build), so a red suite cannot merge.

Enforcing the **Python lint gate** in CI is a near-term follow-up:
`scripts/lint.sh` currently runs two formatters (`ruff format` + `black`)
Expand Down Expand Up @@ -377,12 +362,13 @@ Three things remain the **consumer's** responsibility:
[`MartinCastroAlvarez/django-admin-api`](https://github.com/MartinCastroAlvarez/django-admin-api/blob/main/SECURITY.md)
— every API-side concern (each `/api/v1/...` endpoint, the
serializer denylist, the permission gates) lives there.
- [`docs/threat-model.md`](docs/threat-model.md) — STRIDE pass per
endpoint group.
- [`docs/agents/security-expert/AGENT.md`](docs/agents/security-expert/AGENT.md)
— Security Lead role contract.
- [`docs/agents/security-expert/REVIEW_CHECKLIST.md`](docs/agents/security-expert/REVIEW_CHECKLIST.md)
— what Security checks on every PR.
- [`README.md`](README.md) — install + three-repo cross-links.
- [`ARCHITECTURE.md`](ARCHITECTURE.md) — what lives in this repo
vs. the API / MCP siblings.
- The **API package's** own `SECURITY.md` —
[`MartinCastroAlvarez/django-admin-api`](https://github.com/MartinCastroAlvarez/django-admin-api/blob/main/SECURITY.md)
— for every API-side gate (each `/api/v1/...` endpoint, the
serializer denylist, the permission checks).

## 11. Disclosure timeline

Expand Down
60 changes: 11 additions & 49 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,14 @@
# docs/ — long-form documentation
# docs/

What lives here:
Only one subfolder lives here:

- [`api-contract.md`](api-contract.md) — the stable wire contract between
the Django backend and the React frontend. Endpoint paths,
request/response shapes, error codes, ordering/search/pagination rules.
- [`threat-model.md`](threat-model.md) — STRIDE threat model per endpoint
+ supply-chain / logging / privacy sections. The security source of
truth alongside [`SECURITY.md`](../SECURITY.md).
- [`extensions.md`](extensions.md) — how consumers extend the UI without
writing React (`register_field_type`, the per-model panel hook).
- [`data-layer.md`](data-layer.md) — the `@dar/data` one-way data-flow
rules (the only package that talks to `@dar/api`).
- [`ux/`](ux/) — the UX contract the SPA implements: principles,
navigation, primary flows, responsive, theming, accessibility, PWA,
loading/error states.
- [`consumer/`](consumer/) — real-adopter feedback + pilot requirements
(input that drives the roadmap; **not** a usage guide).
- [`screenshots/`](screenshots/) — UI screenshots embedded in the README.
- [`agents/`](agents/) — durable inter-agent coordination artifacts:
- [`decisions.md`](agents/decisions.md) — append-only log of accepted
architectural decisions.
- [`open-questions.md`](agents/open-questions.md) — questions awaiting
resolution.
- [`pr-workflow.md`](agents/pr-workflow.md) — the author/reviewer/merger
protocol for autonomous PR ops.
- [`autonomy-policy.md`](agents/autonomy-policy.md) — tier rules + kill
switches governing what may be auto-merged vs. human-gated.
- Per-role subteam docs live under `agents/` (product-manager,
security-expert, software-architect, consumer).
- [`screenshots/`](screenshots/) — the PyPI / GitHub landing-page
screenshots referenced from the root `README.md`. The images are
raw-served via GitHub from `main` so the PyPI long-description renders
them. See `screenshots/README.md` for the capture contract.

What does **not** belong here:

- Status / progress / changelog data — that lives on the
[Project board](https://github.com/users/MartinCastroAlvarez/projects/3),
in the [Issues](https://github.com/MartinCastroAlvarez/django-admin-react/issues)
list, and as merged PR history.
- Announcements / Q&A / community chatter — that goes in
[GitHub Discussions](https://github.com/MartinCastroAlvarez/django-admin-react/discussions).
- Per-PR review conversation — that goes on the PR itself.
- Code or configuration — those live in their own directories.
- Folder READMEs — each folder owns its own.
- Secrets, tokens, or anything sensitive. This directory is committed
and public.

Future docs (added when their PRs land):

- `installation.md` — deep-dive install + customization guide (the
[README](../README.md) quickstart is the current entry point).
- `release.md` — the release procedure (gated by repo owner; see
[`SECURITY.md`](../SECURITY.md) §6–§7 for the current gated process).
Everything else lives at the repo root: [`../README.md`](../README.md)
(product), [`../ARCHITECTURE.md`](../ARCHITECTURE.md),
[`../SECURITY.md`](../SECURITY.md). The wire contract for
`django-admin-rest-api` (this package's API dependency) lives in the
**[API repo](https://github.com/MartinCastroAlvarez/django-admin-api)**.
95 changes: 0 additions & 95 deletions docs/agents/README.md

This file was deleted.

Loading
Loading