-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Description
Goal
Establish a secure, API-only Laravel 12 (PHP 8.4) foundation for SecPal: multi-tenant isolation, field encryption, blind indexes, Sanctum auth, Spatie Teams RBAC; CI with strict formatting, static analysis, and TDD via Pest. DRY by reusing org-wide .github.
Non-goals
Final user/identity domain decisions (login identifiers, MFA, invites). These will follow later PRs after business clarification.
Repository Scope & Communication
- Scope: Work only in
SecPal/api. Do not modify other repos (except referencing org-wide.githubviaworkflow_call). - Language: GitHub (issues/PRs/commits/docs) English-only. Direct questions to the owner in German (VS Code) are allowed.
Principles
- TDD, Quality First, DRY, Clean over quick
- PEST-only (no direct PHPUnit); coverage ≥80%
- Small PRs (~400–600 LOC) with Conventional Commits
- Sanctum (guard
api), Spatie Teams (tenant_idscope) - Field encryption (Eloquent
encryptedcasts), blind indexes (HMAC) for equality search - No LIKE/range/sort on encrypted fields; FTS only via
tsvector - Envelope key management without external KMS (KEK file, per-tenant DEK/idx_key, rotation)
- DRY: Reuse org-wide
.githubworkflows/templates (fail CI if local duplicates appear)
Acceptance Criteria
- All PRs green in CI (Pint PSR-12, Larastan, Pest ≥80% coverage)
- Reuse of org
.githubvia reusable workflows (no local copies; duplication causes CI failure) - API-only with Sanctum (stateless PATs) and Spatie Teams fully wired
- Multi-tenant scope enforced; no cross-tenant access (tests)
- No plaintext in DB/logs/responses (tests)
- Rotation/rebuild commands exist & are tested
- Each PR ≤ ~400–600 LOC where feasible; else split
- PR template checklist completed; linked to this issue and to Project
Work Plan (each item = its own PR; reference this issue)
- PR-0: Org
.githubDRY & Preflight
- Reference org reusable CI viaworkflow_call(Laravel CI); add only minimal repo glue.
-.editorconfig,.gitattributes(LF) if not inherited.
- README (preflight checks, KEK creation).
- PEST smoke tests (env/config). - PR-1: Migrations & Base Schema
- Tables:tenant_keys(dek_wrapped/nonce, idx_wrapped/nonce, key_version, created_at);person(tenant_id, *_enc, *_idx, created_at).
- Indexes: (tenant_id, email_idx), (tenant_id, phone_idx). Optional FTS:note_tsv+ GIN.
- PEST schema tests. - PR-2: Services — KeyStore & BlindIndex
-config/keys.php;KeyStore(libsodium xchacha20-poly1305);BlindIndex(normalize/HMAC).
- PEST tests: KEK load, unwrap, HMAC determinism; no plaintext. - PR-3: Tenant Middleware & RBAC Wiring
- MiddlewareSetTenant(path orX-Tenant), membership check (Spatie),PermissionRegistrar::setPermissionsTeamId($tenantId).
- Tests: missing tenant 400/403, valid tenant, isolation. - PR-4: Model/Observer & Repository
-Personmodel:encryptedcasts;$hiddenprotects*_enc/*_idx; observer computes_idxfrom transientemail_plain/phone_plain.
-PersonRepository:findByEmail,createOrUpdate.
- Tests: encryption cast, hidden, blind-index search. - PR-5: API Endpoints (JSON)
- Routes under[auth:api, SetTenant]: POST/tenants/{tenant}/persons, GET/tenants/{tenant}/persons/by-email.
- Spatie middleware (permission:person.write/read).
- Feature tests: 201/200/403; no_enc/_idxexposure. - PR-6: Rotation & Maintenance
- Commands:keys:generate-tenant,keys:rotate-kek,keys:rotate-dek,idx:rebuild.
- Tests: re-wrap/re-encrypt/index rebuild; search/decrypt still OK. - PR-7: Hardening & Cleanups
- Fix static analysis/CS; README security notes (KEK, rotation, FTS leakage).
- Tests: no plaintext in logs/DB.
Technical Guardrails
- Auth: Sanctum PATs (guard
api), stateless - RBAC: Spatie Teams (
team_foreign_key='tenant_id') - Encryption: Eloquent
encryptedcasts for*_enc; blind index*_idx = HMAC_SHA256(normalized_value, idx_key_of_tenant)stored as BYTEA - Normalization: email
lower(trim(v)); phone/badge: digits-only - Envelope keys: KEK file (
KEK_PATH, mode 0600); per-tenant DEK + idx_key wrapped and stored intenant_keys - CI: Reuse org
.githubreusable workflows; fail on Pint/Larastan errors and coverage <80%
Links
- Org reusable workflows & templates:
SecPal/.github - This repo:
SecPal/api - Project: link this issue to the Roadmap/Project board
Notes
- Do not open “question” issues. Ask the owner directly in VS Code (German) for clarifications.
- Keep each PR small (~400–600 LOC). Follow Conventional Commits.
Branch & PR Conventions
- Branches:
feat/<scope>-<desc>,chore/<scope>-<desc>,fix/<scope>-<desc> - PR titles/descriptions: English-only, Conventional Commits
Metadata
Metadata
Assignees
Type
Projects
Status
✅ Done