Add deployment: Dockerfile, compose, proxy config, and docs
One container plus a Postgres behind any TLS-terminating proxy. Nothing is specific to a particular host. The app and API are served from a SINGLE origin. This is not tidiness: browser auth sessions live in per-origin storage, so splitting them across two hostnames makes sign-in loop in a way that presents as a server fault. The short alias redirects rather than serving a second origin. Two safety properties verified by running the image, not by reading the code: - With NODE_ENV=production and no SUPABASE_URL, the process refuses to start and says why. Serving the whole CRM unauthenticated is a worse outcome than failing to deploy, so the failure is deliberate and loud. - In production the development auth bypass does not apply: an unauthenticated request to /api/dashboard returns 401 rather than adopting the first user in the table. The Dockerfile typechecks all six packages as a build gate, so a deploy that does not compile fails at build time rather than in front of a user. Runtime runs unprivileged as `node`, and Postgres is not published to the host. Docs cover the ontology and why it is shaped this way, agent connection for Claude Code / Codex / prime-agent / Buzz, and the provenance rules governing seed data about real people — including how to have your record removed. Verified: image builds, container reports healthy, serves the SPA, enforces auth, and the production guard exits non-zero. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
# The ontology
|
||||
|
||||
Why PIG is shaped the way it is. Read `packages/core/src/ontology.ts` alongside
|
||||
this — the code carries the same reasoning in comments, and it is the version
|
||||
that cannot go stale.
|
||||
|
||||
## The one table that matters
|
||||
|
||||
```
|
||||
capacity_commitment ──┐
|
||||
(what we bought, │
|
||||
at a known cost) │
|
||||
├──▶ allocation ──▶ margin, utilisation, idle
|
||||
│ (what we sold,
|
||||
demand_deal ──┘ at a known price)
|
||||
(what we sold)
|
||||
```
|
||||
|
||||
Margin, utilisation and idle capacity all fall out of that single join. No
|
||||
generic CRM can compute any of them, because none has a concept of a
|
||||
cost-bearing commitment sitting behind the pipeline.
|
||||
|
||||
**Cost is charged against the full commitment, not only the hours that sold.**
|
||||
Unsold hours are already paid for. Charging only the allocated share would
|
||||
report a healthy margin on a block that is losing money — precisely the failure
|
||||
this system exists to prevent.
|
||||
|
||||
## Three teams
|
||||
|
||||
**Supply**, **demand**, and **research**. Research is first-class rather than an
|
||||
afterthought: internal research burn is real capacity consumption competing with
|
||||
revenue for the same GPUs, and margin math that cannot see it is wrong.
|
||||
|
||||
## Pipelines
|
||||
|
||||
**Demand** — `qualification → legal → scoping → proposal → procurement → POC →
|
||||
deployment → expansion`. Note that **legal sits second**. Customers do not hand
|
||||
workloads to an infrastructure provider before paper is executed. Most CRMs put
|
||||
contracting at the end of the funnel and are simply wrong about it here.
|
||||
|
||||
**Supply** — `sourced → qualifying → technical diligence → financial diligence →
|
||||
pricing → contracting → onboarding → live → renewal`. Qualification is split in
|
||||
two because accepting capacity is a two-key decision: engineering judges whether
|
||||
the cluster can do the work, finance judges whether the economics clear. Both
|
||||
verdicts are recorded attributably.
|
||||
|
||||
## Capacity is a shape, not a rectangle
|
||||
|
||||
A commitment carries `shape: {intervals[], quantities[]}` — how many GPUs are
|
||||
held during each interval. Real contracts ramp across tranches and step down at
|
||||
checkpoints. A single start/end/total flattens that and then reports
|
||||
availability that does not exist in the month someone wants it.
|
||||
|
||||
Availability at any instant is therefore:
|
||||
|
||||
```
|
||||
available(t) = shapeQuantityAt(t) − Σ overlapping allocations(t)
|
||||
```
|
||||
|
||||
## Holds reserve; they do not sell
|
||||
|
||||
A live hold removes capacity from everyone else's availability — otherwise two
|
||||
sellers promise the same GPUs — but does not count toward utilisation or
|
||||
revenue, because it has not sold. Conflating the two is how a pipeline of
|
||||
optimistic holds comes to look like a full book. Holds expire on a timer so a
|
||||
stalled deal releases inventory automatically.
|
||||
|
||||
## Service levels come in three shapes
|
||||
|
||||
A compute aggregator generally **cannot** offer a conventional uptime guarantee
|
||||
on capacity it resells and does not control, and says so publicly. So `slaKind`
|
||||
distinguishes:
|
||||
|
||||
- `none` — self-serve, no commitment at all
|
||||
- `credits_policy` — a reliability tier plus service credits. **Not** an uptime
|
||||
guarantee, and must never be displayed as one
|
||||
- `negotiated` — a real signed SLA with committed, measurable metrics
|
||||
|
||||
Remedies matter as much as targets. `remedyType` includes `fee_abatement`,
|
||||
where payment obligations are *cancelled* for affected capacity until service is
|
||||
restored — uncapped in duration and materially better than a capped credit. It
|
||||
cannot be expressed as a credit percentage, so it gets its own representation.
|
||||
|
||||
## Export control is a predicate, not a flag
|
||||
|
||||
US controls on advanced computing apply an **ultimate parent** test that reaches
|
||||
through the corporate tree: an entity can be restricted because of where its
|
||||
parent is headquartered, even when the entity itself sits somewhere
|
||||
unrestricted. Country of incorporation is therefore not a valid key.
|
||||
|
||||
Compliance is evaluated **on the allocation edge** — this buyer, this beneficial
|
||||
owner, this physical jurisdiction — recorded with its reasoning and rule
|
||||
version, and re-evaluated on resale or migration. See
|
||||
`packages/db/src/schema/compliance.ts`. PIG records and surfaces; it does not
|
||||
make the legal determination for you.
|
||||
|
||||
## Evidence
|
||||
|
||||
Agent-derived claims land in `facts` with a confidence score, a band, evidence
|
||||
and a source URL. Only `verified` claims self-apply; anything weaker waits for a
|
||||
human. An agent permitted to write unattributed claims will eventually write a
|
||||
wrong one, and nobody will be able to tell which.
|
||||
|
||||
The same principle governs seed data about real people: every record carries a
|
||||
grade and a citation, authorship is never promoted to employment, and no email
|
||||
address is ever inferred.
|
||||
Reference in New Issue
Block a user