Security
Only what the code enforces
Every claim on this page names the line that backs it. CODED means the check is in the code on the call path. ENFORCED means a test, a database grant or a database policy makes a violation fail. Nothing here is a plan.
11 claims, 44 cited lines.
Tenant isolation by workspace
A workspace is one isolated tenant. The workspace comes from the authenticated key, never from the request body, the path or a header. A call that names another workspace is refused before that workspace is read.
- CODED
A scope that names another workspace is refused with WORKSPACE_REFUSED.
src/ticket16/dispatch.mjs:140
- CODED
A payload that names another workspace is refused.
src/ticket16/dispatch.mjs:171
- CODED
A key for an unserved workspace fails authentication before capability lookup.
src/ticket16/dispatch.mjs:130
- CODED
One authorization function denies every cross-workspace call except a portfolio read.
src/contracts/authorization.mjs:204
- ENFORCED
FORCE ROW LEVEL SECURITY on the record table, so the owner is not exempt.
migrations/ticket9/0001_repository_records.sql:46
- ENFORCED
The policy matches the database role to one workspace id, on read and on write.
migrations/ticket9/0001_repository_records.sql:75
Partner isolation
A partner reads and writes only its own rows. The database check covers writes as well as reads.
- ENFORCED
The partner policy is RESTRICTIVE and FOR ALL, so the workspace policy alone cannot satisfy it.
migrations/ticket9/0001_repository_records.sql:108
- CODED
A partner scope comes from its partner grant and never from caller scope.
src/ticket16/dispatch.mjs:154
- CODED
A partner call is refused by default when partner access is not composed.
src/ticket16/dispatch.mjs:193
Append-only ledger and corrections
A ledger entry is never edited. A refund, a dispute or a manual correction appends a new entry that names the entry it corrects.
- ENFORCED
The application role holds SELECT, INSERT and UPDATE. It holds no DELETE.
migrations/ticket9/0001_repository_records.sql:63
- CODED
A refund appends a refund-correction entry.
src/ticket6/index.mjs:745
- CODED
A commission approval is immutable once it exists.
src/ticket6/index.mjs:2035
- CODED
A reject is a separate append-only record. Nothing edits an approval or a reject.
src/ticket6/index.mjs:2051
Read-only Stripe access
Parka makes one Stripe call, a read of the event list. Every other Stripe call is refused in code before the network is reached.
- CODED
The client allows only GET https://api.stripe.com/v1/events.
src/runtime/stripe-client.mjs:32
- CODED
Any method other than GET is refused before fetch is reached.
src/runtime/stripe-client.mjs:36
- CODED
A Stripe write is refused with STRIPE_WRITE_REFUSED.
src/ticket10/index.mjs:161
- ENFORCED
Gate 14 pins the flags and surfaces of the Stripe capability.
src/gate14/checker.mjs:38
Parka never moves money
Parka calculates what a partner is owed. You pay the partner with your own rails. A person records the receipt.
- CODED
There is no charge, transfer or payout call anywhere in the client.
src/runtime/stripe-client.mjs:32
- CODED
Recording a payout takes an external reference and operator evidence for a payout that already happened.
src/ticket7/index.mjs:292
- ENFORCED
Recording a payout receipt is pinned as a human gate.
src/gate8/checker.mjs:46
API key hashing
Only a peppered hash of an API key is stored. The plaintext appears once, at mint, and never again.
- CODED
The stored hash is HMAC-SHA256 over the key with a runtime pepper.
src/ticket16/keys.mjs:48
- CODED
Verification compares in constant time.
src/ticket16/keys.mjs:74
- CODED
A revoked key fails closed.
src/ticket16/dispatch.mjs:58
- CODED
Postgres stores a second digest over a database-local secret, so a copied hash is useless.
migrations/ticket18/0002_db_key_digest.sql:105
Human gates
An agent cannot run a human gate. The call creates an approval request and runs nothing. Only a person approves it, and approval runs the stored call as that person.
- CODED
A capability is automation safe or it is a human gate. An incoherent pair is refused at declaration.
src/contracts/manifest.mjs:67
- CODED
A human gate refuses every actor kind except human, and refuses the mcp surface.
src/contracts/authorization.mjs:214
- CODED
A served key never carries human presence.
src/ticket16/dispatch.mjs:144
- CODED
A human gate through the dispatcher creates an approval request. The implementation is not called.
src/ticket16/dispatch.mjs:199
- ENFORCED
Gate 8 dispatches every included surface and asserts every human gate stays off MCP.
tests/gate8.test.mjs:234
An agent can never widen its own rights
A credential change is a human gate. An agent cannot grant itself access, and it cannot approve its own request.
- CODED
Binding a partner key to a grant is declared a human gate.
src/partner-access/service.mjs:30
- CODED
A grant takes its program, relationship and partner identity from the key record, never from the payload.
src/partner-access/service.mjs:81
- CODED
Minting a key is declared a human gate. Revoking one stays automation safe.
src/ticket16/index.mjs:134
- CODED
Approve and reject cannot be the target of an approval request.
src/approvals/index.mjs:102
- ENFORCED
A partner key cannot grant access and cannot approve its own request.
tests/k0-grant-access-human-gate.test.mjs:347
Audit trail
Every admitted or refused partner call appends one audit row. A row is never updated or deleted, and it never holds a full credential.
- ENFORCED
The application role is granted SELECT and INSERT only.
migrations/partner-access/0003_partner_audit_log.sql:45
- ENFORCED
A row holds at most a 16 character credential prefix, and the check refuses the key prefix.
migrations/partner-access/0003_partner_audit_log.sql:19
- CODED
The audit entry is written whether the call is admitted or refused, and it commits with the refusal.
src/ticket16/dispatch.mjs:194
Secrets are not returned or logged
A runtime secret is not returned through a surface and not written to a log line.
- CODED
A secret is held in a wrapper. Only one method returns the value.
src/runtime/config.mjs:12
- CODED
A redactor removes every configured secret from an output string.
src/runtime/config.mjs:41
- CODED
The health body is redacted before it is sent.
src/runtime/served.mjs:71
- CODED
A CLI refusal prints a code and no message, because a message can quote a connection string.
src/ticket16/cli.mjs:34
One refusal name on every surface
The API, the CLI and MCP return the same refusal name for the same refusal, so one log search covers all three.
- CODED
One refusal-to-status map covers the served surface.
src/ticket16/transport.mjs:46
- CODED
The MCP error carries the same code in the message and in the data.
src/ticket16/transport.mjs:378
- ENFORCED
One wrong-workspace call returns the same name on the API, the CLI and MCP.
tests/adr0005-f1-surface-parity.test.mjs:349
What this page does not claim
- Parka holds no certification and no audit report. There is none to show.
- There is no public runtime health endpoint, so this site publishes no uptime number and no status page.
- Applying a migration to a real database is its own human gate in Parka. A claim about a database grant is a claim about the schema the migration declares.
- The operator identity on a command-line gate is self asserted. Nothing verifies that a person is at the keyboard.
- Nobody on the site team has watched a live Parka runtime, so no claim here is an observation.
Reporting something
Mail us if you find a problem. Tell us what you did and what you saw. We read every report and reply by email.