Secure Development Policy¶
| Field | Value |
|---|---|
| Status | draft |
| Owner | INFRA |
| Applies to | All Partile code: backend (FastAPI/Python), mobile (React Native/TS), infra-as-code, and the Atelier development workflow. |
| Review cadence | Annual, or on material change to the stack or threat model. |
| Mapped controls | SEC-01–07 and SEC-10 (auth, authz, intake hardening, secret hygiene, rate limiting, signed-token validation), SEC-15 (IDOR regression test), OPS-04 (reviewed PRs). |
| Evidence | partile-infra: app/models.py, app/api.py, app/auth/*, repositories/*; readiness/threat-model-and-auth-review.md; Git/PR history. |
| Exception handling | A known weakness shipped knowingly is logged as risk-accepted (risk-management-policy.md) with a fix milestone. |
Purpose¶
Make security properties a build-time default in Partile's code, grounded in the patterns already implemented in the backend rather than generic SDLC theory.
Secure-by-default patterns (already in the codebase — keep them)¶
- Input is whitelisted, not blacklisted, then sanitized. Presence intake uses
a Pydantic whitelist +
extra="forbid"+ banned-field rejection; 422 errors are sanitized toloc/msg/typewith no echoed values (SEC-06). - Don't store the sensitive form. No raw boarding-pass artifacts; session
tokens stored only as SHA-256 hashes; OAuth tokens never persisted; LinkedIn
id_tokenverified via JWKS before identity is trusted (SEC-01, SEC-05, SEC-10, PRIV-06). - Authorize in the data layer. Object-level checks live in SQL; non-visible → 404, no existence leak (SEC-04). New read paths must follow this pattern.
- Secrets never logged. Access logs are off in the container; no secret values in logs or errors (SEC-05).
Requirements for new code¶
- Threat-model the change when it touches auth, data, matching, messaging,
safety, or admin surfaces — update
readiness/threat-model-and-auth-review.md. - No new IDOR. Every object read enforces ownership/visibility in the query; add/extend the cross-user 404 regression test (SEC-15).
- Enforce safety predicates in code, not docs. Block separation, consent
tiers (
ai-ml-data-governance-policy.md), and rate limits are enforced by the code path, with smoke tests (safety_smoke.py,rate_limit_smoke.py). - No secrets in source. Configuration via env/Secret Manager; safe labels only in repo.
- Validate and minimize at the boundary. Reject unknown fields; persist only the minimal derived data the feature needs.
- Dependencies are added deliberately and tracked for vulnerabilities
(
vulnerability-management-policy.md).
Review & merge¶
All code lands via reviewed PRs through the Atelier checkpoint and merges to
main (change-management-policy.md, ../procedures/release-review-procedure.md).
Security-relevant PRs update the control register row.
Production preflight¶
Before any real-user data, the security preflight gates apply: assert
APP_ENV=production (dev routes unmounted), Cloud Run edge/origin TLS, private
Cloud SQL and Redis access through the VPC connector, rate limits live, sweeps
running, block enforcement live, IDOR test green, and secrets confirmed in GCP
Secret Manager (SEC-05, SEC-08, SEC-09; see
readiness/threat-model-and-auth-review.md and
technical/infrastructure-and-deployment.md).
Exceptions¶
Shipping a known weakness (e.g. deferring session idle timeout/rotation or
production HA/restore-drill maturity)
requires a dated risk-acceptance with a compensating control and a fix milestone,
recorded on the control row and in the READINESS.md decision log.