Principles — Global Invariants
Principles — Global Invariants
Section titled “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.
Data & Privacy
Section titled “Data & Privacy”- 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.
Tenancy & Access
Section titled “Tenancy & Access”- 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_leadershipandpeople_teamboth 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.
- Functional roles:
Build & Interface
Section titled “Build & Interface”- 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:
- 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 leakedSETacross pooled connections breaks PR-04). - pgvector as a first-class column type (AI features).
- Composes with raw SQL for recursive graph queries (actions→outcomes→goals recursive CTEs) without fighting the abstraction.
- Managed migrations — versioned, not hand-rolled.
- 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.
- Per-transaction RLS context — sets tenant identity (e.g.
Release
Section titled “Release”- 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.