This model covers the M0 local scaffold and the specified future PlatePilot beta: an adult-only mobile experience, REST API, asynchronous meal analysis, two-adult households, internal support surface, and third-party providers.
M0 has no production deployment, real adapters, customer dataset, or complete identity/authorization flow. Controls marked required are design requirements, not claims about current behavior.
Age assurance, jurisdictional privacy classification, consent wording, and support verification need legal/privacy review before beta.
| Asset | Sensitivity | Primary concern |
|---|---|---|
| Credentials, sessions, recovery factors | Restricted | Account takeover |
| Meal photos and object references | Restricted | Intimate-context disclosure, location metadata, unauthorized reuse |
| Diary, water, plan, and nutrition records | Confidential | Profiling, embarrassment, inference of health or routine |
| Adult identity and household graph | Confidential | Stalking, coercion, unauthorized sharing |
| Subscription and entitlement state | Confidential | Fraud and improper denial of access |
| Body facts and goals (sex, height, weight, activity, targets) | Restricted | Health inference, body-image harm if shown carelessly; never shared with a household peer |
| Exports and deletion evidence | Restricted | Bulk disclosure or incomplete erasure |
| Provider credentials and webhook secrets | Restricted | Vendor impersonation and data exfiltration |
| Audit events and operational telemetry | Confidential | Exposure through logs or loss of accountability |
| Contracts, code, and deployment artifacts | Internal | Supply-chain compromise and tampering |
flowchart LR
Device["Adult device<br/>untrusted client"]
Edge["Future public ingress"]
App["PlatePilot service zone"]
Data["Restricted data zone<br/>database and objects"]
Ops["Operator/support zone"]
Vendor["External provider zones"]
Device --> Edge --> App --> Data
Ops --> App
App --> Vendor
For M0, the equivalent zones are the developer host, loopback-bound Docker services, application processes, repository, and package registries. Localhost is not a security boundary against other processes on the host.
| Abuse case | Impact | M0 control | Required before beta |
|---|---|---|---|
| Guess or steal an adult’s session | Full account exposure | No production identity integration | Strong managed identity, secure token storage, rotation/revocation, rate limits, recovery safeguards |
| Change an ID to read another adult’s record | Cross-account disclosure | Every repository query filters by the caller’s own adult profile; the only cross-adult reads are shared plans (mutual opt-in, read-only) and shared daily totals (owner opt-in); ownership is covered by unit and integration tests | Production identity and an exhaustive authorization test matrix |
| Coerce or trick a second adult into sharing | Privacy and safety harm | Single-use 7-day invitation codes that carry no data; independent acceptance; two per-adult sharing switches default off; plans shared only when both opt in; leaving is unilateral and clears sharing; nothing is ever copied between adults (ADR-0008) | Coercion and post-separation research (TM-04), safety review of copy, rate limits on code guessing |
| Use a household role to export/delete the other adult | Bulk loss/disclosure | Export and deletion act only on the caller’s own profile; export contains only the fact sharedWithAnotherAdult; deletion requires X-Confirm-Deletion equal to the caller’s own ID, removes retained photos before rows, and leaves the other adult’s household and rows untouched; both audited |
Stronger re-verification, cooling-off policy, vendor deletion evidence, backup restore suppression |
| Upload a polyglot, oversized, corrupt, or malicious file | Availability or parser compromise | M1 checksum binding, version capture, Sharp decode, and byte/dimension/pixel limits | Production malware strategy, isolated processing, and timeouts remain pending |
| Preserve EXIF location or faces beyond need | Context disclosure | Raw uploads are quarantined, auto-oriented, re-encoded without metadata, and exact-version deleted before provider processing; only sanitized bytes can reach processing or optional retention | Production face-detection validation and vendor handling review remain pending |
| Replay an upload/job/webhook | Duplicate charges or records | Async contracts and synthetic mocks | Idempotency keys, signed webhooks, freshness checks, deduplication, bounded retries and DLQ |
| Tamper with an AI estimate | Misleading wellness information | Deterministic mock only | Schema/range validation, provenance, provisional label, review/edit/manual path |
| Generated meal plan includes an allergen or implies a medical target | Physical harm or medical framing | Allergens limited to the 14 EU vocabulary; recipe ingredients tagged; generator filters and the API re-checks every meal; each item exposes its allergens and copy says to check labels; focus replaces numeric goals; nutrition labelled as a synthetic per-serving estimate (ADR-0010) | Allergen data quality review for any real provider, dietitian/legal review of copy, user testing of the "check labels" wording |
| Location used for planning reveals where an adult lives | Context disclosure | Only country plus city or postal code is accepted and stored; a street address is rejected by schema; location is used for product names, sections, and units only | Review whether city/postal code is needed at all once a real grocery-data provider is chosen |
| Exhaust analysis quota or queue | Cost and availability impact | Per-adult monthly photo-analysis allowance enforced server-side before a new upload is authorized (403 analysis_allowance_exhausted); usage counted from analysis jobs; manual entry unaffected (ADR-0009) |
Household-level limits, rate limiting, backpressure, budget alarms, abuse review |
| Substitute mocks or debug mode in production | False output or weakened controls | No deployment; strict configuration foundation | Environment allowlist, startup failure, deployment policy and tests |
| Inject sensitive values into logs/errors | Long-lived disclosure | Typed errors and synthetic-data rule; M1 audit events are a strict allowlist (actor, action, public resource ID, request ID, outcome, error code) that rejects unknown fields and free text | Structured redaction, payload exclusion, access controls, retention enforcement and tests |
| Abuse internal support access | Broad data disclosure | Admin has no customer-data access; every sensitive mutation (onboarding, diary writes, photo intake and worker steps, plan changes and confirmations, household invitations/sharing/leave, subscription changes, alert preferences, export, deletion) is recorded to an in-process audit sink with public IDs only | Least-privilege roles, reason codes, approval for high-risk actions, immutable audit, periodic review |
| Compromise a dependency/build | Code execution or secret theft | Lockfile and validation | Dependency review, provenance/SBOM policy, protected CI, artifact signing and scanning |
| Lose a device with offline drafts | Diary/photo disclosure | M1 SQLCipher command/photo-job stores, strict payload/UI schemas, per-adult SecureStore preferences, dedicated temp-media sweep, and sign-out destruction | Device/native security review, screen/privacy controls, and remote-session revocation |
| Infer that a child uses the product | Safety/legal impact | Adult-only policy | Age gate, no dependent/minor fields, support escalation, deletion path |
quarantine/, are decoded, auto-oriented, and re-encoded as JPEG/PNG
without EXIF (including GPS). The API stores the sanitized checksum and immutable
processing/ version, then deletes the exact raw version. One-day lifecycle rules cover both
prefixes as a crash fallback. Providers and optional 365-day retention receive only sanitized
bytes.sharedWithAnotherAdult;
deletion cascades only the adult’s own rows, drops an empty household, and leaves a receipt
holding a one-way subject hash.No real vendors are connected in M0. LogMeal, Spoonacular, RevenueCat, Cognito, notification, and health adapters are intentionally absent.
Before enabling any provider:
Provider contracts reduce coupling; they do not transfer PlatePilot’s privacy responsibility.
| ID | Risk | State / next evidence |
|---|---|---|
| TM-01 | No production identity or object authorization | Open; threat review and authorization test matrix before beta |
| TM-02 | End-to-end deletion propagation to future real providers is not implemented | Open; local source and retained-object deletion are enforced, but vendor deletion evidence is still required |
| TM-03 | Native encrypted recovery behavior differs across supported devices | Mitigated in M1 with SQLCipher command/photo-job stores, strict fail-closed schemas, ACK/conflict tests, and destructive sign-out; simulator/device validation remains required |
| TM-04 | Household coercion and shared-record semantics need research | Partially mitigated: ADR-0008 fixes the shared-record model (opt-in, mutual, read-only plans; totals-only summaries; unilateral leave) and the API enforces it with tests. Still open: adult safety review, coercion and post-separation usability evidence, rate limits on invitation-code guessing |
| TM-05 | Vendor contracts and data-use terms are unreviewed | Open; security/privacy assessment for each adapter |
| TM-06 | File-processing and content-safety pipeline is undefined | Open; upload design, limits, isolation, and malformed-file tests |
| TM-07 | Confirmed performance targets lack measurement evidence | Open; test cached dashboard under 1 second, normal API p95 under 500 ms, and analysis p90 under 15 seconds |
| TM-08 | Export/deletion workflow and legal response periods are unset | Partially mitigated: per-adult JSON export and verified deletion (confirmation header, retention-bucket purge first, cascading transaction, receipt) are implemented and exercised locally. Still open: approved legal policy, re-verification method, cooling-off, vendor evidence, backup restore suppression |
| TM-09 | Cloud logging, audit immutability, and support roles are not built | Partially mitigated in M1: sensitive mutations emit schema-validated, privacy-safe audit events (succeeded, rejected, and failed outcomes) plus api.request.duration and meal_analysis.completion.duration metrics through in-process sinks only (stdout JSON locally, memory in tests); no cloud delivery, durability, or immutability yet. Still open: durable immutable storage, retention, alerting, support roles, and access review |
| TM-10 | Adult-age assurance may be bypassed | Accepted residual risk for M0; method and escalation pending beta review |
| TM-11 | Mock billing allowance is per adult and may diverge from commercial policy | Accepted for local development (ADR-0009): configurable per-adult monthly allowance, no charges, lazy trial start. Needs commercial/legal decision on household versus per-adult allowances and explicit trial consent before beta |
| TM-12 | Generated plans depend on ingredient allergen data that a mock cannot guarantee for real recipes | Accepted for local development (ADR-0010): synthetic library with hand-tagged allergens, double filtering, per-item allergen exposure, and label-check copy. Before any real provider: allergen data quality assessment, dietitian and legal review, and a kill switch to manual planning |
Revisit this model for every new data category, provider, household-sharing rule, offline store, support permission, or deployment topology change.