Skip to content

Principles — Global Invariants

Every spec inherits these. Page specs reference principle IDs (PR-xx); they do not redefine them. A spec that needs an exception must state it explicitly and get owner sign-off. Acceptance criteria and contract tests may be tagged to PR-xx as well as FR-xx.

Status: stub — to firm up after the 2026-06-10 stack sign-off and the backend/DB ownership decision. See docs/operating-model.md.


  • PR-01 — HomeRun is the source of truth for personal/HR data. Gospl does not duplicate it. (Promoted from Personal Page FR-19.) Boundary: this covers personal/HR data only. The org chart / reporting line is Gospl-mastered (decided 2026-06-10) — it is org structure, not personal data, and drives access (see PR-06 and _platform/identity-and-access.md §5). HomeRun’s hierarchy, if any, is not authoritative for Gospl.
  • PR-02 — Data minimisation. Gospl persists only what core functionality needs for a user: name, team, reportingLineId, jobTitle. No additional personal data is stored. A schema/contract check fails if any other personal field is persisted. (Promoted from Personal Page FR-22.) Core functionality = org chart, team page, goals/capabilities, role page.
  • PR-03 — GDPR posture. Removing a legacy data section requires a confirmed migration/deletion plan before removal (cf. Personal Page OQ-06). Retention and right-to-erasure handling: TBD.
  • PR-04 — Everything is tenant-scoped. Every persisted entity carries a tenant identity. Cross-tenant read or write MUST be impossible. Enforcement owner (Gospl RLS vs external-team implementation) pending the backend/DB ownership decision; either way it is verified by contract test.
  • PR-05 — Server-authoritative field visibility. When a viewer may see a subset of a resource, the server omits restricted fields from the response body — it does not rely on the client to hide them. (Pattern set by Personal Page FR-10, Mojo AI insights.)
  • PR-06 — Permission model. Access is decided on two axes, combined per request. Canonical spec: _platform/identity-and-access.md.
    • Functional roles: employee, people_team, senior_leadership, admin (+ feature-scoped elevated grants, e.g. Mojo AI-insight visibility on Personal Page FR-11). senior_leadership and people_team both carry org-wide read for People-area data (Weekly Summary FR-38).
    • Relationship to the resource owner (org-chart-derived, per-resource): self, colleague, line_manager (owner is a direct report), manager_of_managers (owner is anywhere below in the reporting chain).
    • Rule: a viewer may act on a resource if a functional role grants it OR their relationship to the owner grants it. Default-deny otherwise.
    • Reference visibility ladder (from Weekly Goals §5, generalised): own → direct reports (line manager) → full chain (manager of managers) → org-wide (People Team/Admin). Features inherit this ladder; they do not invent their own.
    • Still gates RLS design and is a pre-build dependency; the matrix lives in the platform spec, not in feature specs.
  • PR-07 — Contract-first. Each piece of functionality has an API contract (OpenAPI 3.1 by default) in /contracts, authored by Gospl, implemented by the external team. The contract is the single source for handoff, client types, mock server, and wiki API docs.
  • PR-08 — The ID join key. US/FR/OQ/PR IDs join spec ↔ contract ↔ test ↔ wiki. Every Must-Have FR has a passing, ID-tagged test (incl. its contract test) before it counts as met.
  • PR-09 — Spine is canonical. The actions→outcomes graph (_spine/goals-outcomes.md) owns its entity IDs. Other specs reference those IDs; they never redefine the graph.
  • PR-10 — Contract change protocol. Contract changes are versioned and signed by both Gospl and the external team before either side moves. (Mitigates contract drift.)
  • PR-13 — Data layer requirements. The data/persistence layer (ORM or query builder) is an internal implementation detail behind the API contract — product choice is the external team’s, but it MUST satisfy:
    1. Per-transaction RLS context — sets tenant identity (e.g. SET LOCAL app.tenant_id) inside each transaction, never session-level on a pooled connection (a leaked SET across pooled connections breaks PR-04).
    2. pgvector as a first-class column type (AI features).
    3. Composes with raw SQL for recursive graph queries (actions→outcomes→goals recursive CTEs) without fighting the abstraction.
    4. Managed migrations — versioned, not hand-rolled.
    5. End-to-end TypeScript types aligned with the contract types. Recommendation (product choice left to external team): a type-safe query builder (Drizzle or Kysely) over a heavy ORM. Prisma flagged as the weakest fit here — RLS + connection pooling + recursive CTEs + pgvector are exactly its rough edges. Chosen product: TBD at 2026-06-10 stack meeting.
  • PR-11 — Whole release, never sectional. V1 ships as one whole across people, clients, org. Build order may be sliced; release order may not.
  • PR-12 — External dependencies behind flags. FRs depending on third-party APIs (Mojo, Insights, HomeRun) sit behind feature flags so the whole-release gate is never held hostage to a third-party slip.