feat(sdd): add .specify scaffold — constitution, AGENTS, personas, templates, example, RTM
Introduces the SDD root: a v1.0.0 constitution and machine-readable AGENTS.md grounded in the project's real conventions; six EARS-aware persona spec-review checklists that cross-reference .claude/personas/; feature-spec/ADR/threat-model/ api-contract templates; a fully worked _example feature; a living RTM; and an adrs/ pointer that reuses the existing docs/adr/ archive. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# ADR-001 (feature-local) — Avatars reuse the archive bucket under an `avatars/` prefix
|
||||
|
||||
**Status:** Accepted
|
||||
**Date:** 2026-06-13
|
||||
**Issue:** #<example> (profile picture upload)
|
||||
|
||||
> **Feature-local ADR.** This decision is scoped to the avatar feature and lives with its
|
||||
> spec. A decision with project-wide reach is promoted to the permanent archive at
|
||||
> `docs/adr/` with the next free number. (For the worked example, it stays local.)
|
||||
|
||||
## Context
|
||||
|
||||
Avatars are small binary objects keyed per user. The project already runs MinIO with a
|
||||
single archive bucket and a `FileService` abstraction used by document uploads. We must
|
||||
decide where avatar bytes live without adding operational surface that the self-hosted
|
||||
Compose deployment has to learn about.
|
||||
|
||||
## Decision
|
||||
|
||||
Store each avatar in the **existing archive bucket** under the deterministic key
|
||||
`avatars/{userId}`, written and read through the existing `FileService`. No new bucket, no
|
||||
new env var, no new Compose service or bucket-bootstrap step.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
| Option | Pros | Cons | Reason rejected |
|
||||
|---|---|---|---|
|
||||
| Reuse archive bucket, `avatars/` prefix | No infra change; reuses `FileService`; idempotent overwrite | Mixes avatars with documents in one bucket | **Chosen** — least operational cost; prefix keeps them logically separate |
|
||||
| Dedicated `avatars` bucket | Clean separation; independent lifecycle/policy | New bucket + bootstrap step + env var + Compose idempotency test | Operational overhead not justified for small, low-value objects |
|
||||
| Store bytes in PostgreSQL (`bytea`) | One datastore; transactional with the row | Bloats the DB and backups; streaming images via JPA is awkward | Wrong tool; MinIO already exists for blobs |
|
||||
| External CDN / object store | Offloads bandwidth | New third-party dependency + secret + ADR; conflicts with self-hosted goal | Contradicts the self-hosted infrastructure stance |
|
||||
|
||||
## Consequences
|
||||
|
||||
- No deployment change ships with this feature — only a Flyway column and code.
|
||||
- Avatars and documents share a bucket; any future per-object lifecycle policy must filter
|
||||
by the `avatars/` prefix.
|
||||
- The deterministic key (`avatars/{userId}`, no random suffix) makes replace an overwrite,
|
||||
so there is no orphan-cleanup obligation (REQ-001).
|
||||
- If avatars later need independent retention or a public CDN, this ADR is superseded by a
|
||||
project-wide ADR in `docs/adr/`.
|
||||
|
||||
## References
|
||||
|
||||
- [`./spec.md`](./spec.md), [`./design.md`](./design.md)
|
||||
- [constitution §5 Dependency Policy](../../constitution.md#5-dependency-policy)
|
||||
Reference in New Issue
Block a user