# Engineering, release, and QA practices

These practices follow Pactuno's Hatchable runtime constraints. The generated project `AGENTS.md` is authoritative for platform-specific limits.

## Code boundaries

- Browser code belongs in `public/`; routed backend code in `api/`; shared backend helpers in `lib/`; schema changes in `migrations/`.
- Hatchable serves source directly. Do not add a build step, framework server, ORM, native package, or external runtime module import.
- Keep customer, operator, and public demo surfaces separate by route and authorization.
- Use accessible labels, stable IDs, explicit loading/error/empty states, responsive layouts, and cohesive handlers.

## API conventions

- Every API declares `access` and supported `methods`.
- Normalize and validate inputs before querying.
- Use parameterized SQL; never interpolate user input.
- Return stable JSON shapes and suitable codes: 400 invalid input, 401 sign-in/MFA required, 403 forbidden, 404 missing, 409 conflict, 500 unexpected failure.
- Use a database transaction for related writes that must succeed or fail together.
- Treat email, storage, and scheduling as fallible side effects; report outcomes accurately.
- Authorize in the server handler even when the UI hides the action.
- Audit consequential account, plan, membership, and project changes.

## Database changes

- Add schema changes as ordered, forward-compatible migrations; never rewrite an already-applied migration.
- Inspect the live schema before designing a migration.
- Backfill and validate before enabling constraints.
- Document key tables, ownership columns, and relationships.

## Release workflow

1. Read project instructions; inspect affected code, schema, and production logs.
2. Record intent and update an ADR for structural decisions.
3. Implement one coherent change and update affected docs.
4. Run the Hatchable dry-run deploy validator.
5. Exercise changed APIs as authorized and unauthorized callers where supported; inspect actual response shapes.
6. Inspect browser routes and key state transitions.
7. Deploy with a useful user-facing intent and summary.
8. Confirm the deployed version and check new error logs.

## Manual QA matrix

| Check | Expected result |
|---|---|
| `/` | Links to customer sign-in, public demo, docs, and Global Admin |
| Signed-out `/app/` | Email-code sign-in; return to customer workspace |
| Signed-out `/admin/` | Email-code sign-in; return to admin console |
| Non-admin opens `/admin/` or calls admin API | No admin data or actions; API denies access |
| Anonymous calls `/api/projects` or `/api/project` | Rejected by the signed-in-user edge gate |
| Open company | Company users render or a useful empty/error state appears |
| Pending/invalid tier change | Clear 4xx; no null-ID database error |
| Removal allowed/denied | Cleanup after success; otherwise access suspended and records preserved |
| Customer navigation | Customer sections remain visible; no admin navigation |
| `/customer-demo/` | Fictional public preview loads; customer data is not exposed |
| `/login?next=/app/demo-start.html` | Email-code sign-in creates an idempotent, user-owned sample workspace; account is not Global Admin |
| Global Admin opens `/app/` or calls `/api/projects` or `/api/project` | Redirected to operator console in browser; APIs deny customer project data |
| `/api/project` as non-admin on another account's project | Denied; no cross-customer project detail |
| Global Admin notification bell | New user additions, registrations and first-time customer onboarding appear; unread badge is accurate |
| Release | Dry run passes; version is live; no new 5xx from changed flows |

## Documentation policy

Update the route map, API catalogue, security rules, user flow, or QA matrix in the same change whenever its behavior changes.