Security review packet
Control detail
Written for a questionnaire rather than for a first impression. Each control below states its mechanism, its boundary, and whether it is live today, written down but not built, or not held at all. The security overview is the shorter read.
Tenant isolation is enforced by the database
LiveEvery application table is protected by Postgres Row Level Security (RLS), and every one of them uses forced RLS. Standard RLS protects ordinary roles; forced RLS also applies those policies to the table owner, closing an exemption that could otherwise affect migrations, support queries or background work. A schema trigger applies the same setting to new tables as they are added, so the property is a rule rather than a habit.
Application authorization still checks the signed-in person’s organization and role. RLS provides the independent data-layer boundary if an application query is incomplete or incorrect. No policy in the schema carries an unconditional predicate, and the unauthenticated role holds no privilege in the application schema at all — a signed-out request reaches nothing.
A cross-tenant reference is a constraint violation, not a bug
Tenant isolation covers references as well as reads. Relationships such as requirement-to-project are declared on the pair (organization, record), so a row in one organization cannot point at a record in another: the reference does not satisfy the constraint and cannot be written. Further constraints hold the rules that are not about tenancy — that an acceptance names a real person, that the person who publishes a revision is not the person who submitted it, that a monitoring check can never be recorded as if it had blocked something.
Two ways a boundary like this is bypassed
Views and privileged functions receive explicit treatment because both can change which role evaluates a policy. Every view in the schema runs with the caller’s security context, so the caller’s tenant policies remain in force. Every function that runs as its owner pins the namespace used to resolve referenced objects, which is what stops a mutable search path from becoming a privilege-escalation primitive.
Cross-tenant refusal is release-tested
Each release uses a signed-in identity from one organization to attempt reads and writes against other organizations across every tenant-scoped table. The proof uses the same interface as the browser, and every cross-tenant attempt must be refused. The run enumerates the tables from the catalogue rather than from a list, so a table added tomorrow is covered tomorrow; a table added with no organization on it is reported by name instead of being skipped quietly.
Refusal proof last run 18 August 2026, 1 day ago. Outcome: no foreign row was readable and no foreign write was accepted. Policy coverage was last measured on 18 August 2026, 1 day ago, by reading the production database’s own catalogue; this page is built from that measurement rather than from a live query, because the operator credential required to read the policy catalogue is kept off the public request path. Both are the record of a run at a moment rather than a live check, and an administrator of a tenancy can see the same records inside their own workspace.
Encryption and data location
LiveCore application data is stored by Supabase and the application is delivered by Netlify. Encryption at rest and in transit is provided by those managed platforms. When the optional voice assistant is enabled, a tenant-scoped workspace brief and the live conversation are sent to Google Gemini, as listed under subprocessors.
- At rest. The database and its backups are stored encrypted with AES-256 by the managed Postgres platform.
- In transit. Every connection — browser to application, application to database — is TLS 1.2 or above, terminated by the application host and by the database platform. There is no unencrypted listener to reach.
- Where it sits. Customer data is held in the United States and nowhere else. The database runs in AWS
us-east-1(Northern Virginia); the application’s server-side rendering and its API routes run in AWSus-east-2(Ohio). Static pages that carry no customer data are cached on the host’s global network, which is why a page can load quickly from outside the United States without any register content leaving it.
Current scope: customer-managed encryption keys and field-level or column-level encryption are not currently offered. The regions above are the ones in use today, and they are stated as fact rather than as a commitment: there is no contractual residency term, no EU or UK region, and no undertaking not to move a region on notice. A tenancy that needs residency in writing needs a contract clause this page cannot substitute for.
How people sign in, and what a role can reach
LiveIdentity is handled by Supabase Auth. This application never receives, stores or logs a password or a verification code: the credential is exchanged with the auth service, and what comes back is a session. Two methods are available on this deployment today — email and password, or a single-use link sent to a verified address — and either may be followed by a second factor.
- Two-step verification, for local accounts. A time-based code from an authenticator app. Any member may enroll, and once a factor is enrolled it cannot be skipped — every request into a workspace is checked, and a session that has not presented the factor is sent back to do so. SMS and hardware security keys are not offered; the factor is an authenticator app or nothing. Enrollment is not currently demanded of anybody on this deployment. The rule that requires it of the two administrative grades, and the setting that lets a workspace require it of everyone, are built and switched off; they are turned on per deployment rather than on the day the code merged, because demanding a factor stops people who have not been told it is coming. Proposed
- Recovery that is not a back door. Enrollment issues ten single-use recovery codes, shown once and stored only as digests. They are not emailed. Nobody at BoardWalk can issue, read or replace another person’s codes, and no support process can remove somebody’s second factor on request — every route to those codes takes the caller’s own identity and no account argument, so an administrator with full database access can destroy a set and still cannot become its owner. Spending a code removes the authenticator, retires the remaining nine and signs out every session on the account; it does not grant access, and the password is still required afterwards.
- Session lifetime. Eight hours idle, twelve hours absolute, enforced by this application on every request. Reaching either limit revokes the session at the auth service rather than only clearing the browser. The figures are the application’s; the auth service’s own inactivity timeout and session timebox are not set on this project, so a session that never reaches this application is not subject to them.
- Re-authentication before privileged acts. Changing what a member can do, removing access, transferring ownership, minting a synchronization token, changing sign-in policy or touching your own second factor require a proof of identity from the last fifteen minutes. Freshness is read from the auth service’s own signed statement of when a credential was last presented, not from anything this application asserts about itself. The mechanism is live and is currently wired to the account-security acts; the membership and token surfaces are named above as the intended scope and are not behind it yet. Proposed
- Sessions. Held in a cookie marked
SecureandSameSite=Lax, so it is never sent over plain HTTP and never rides a cross-site request. Access tokens are short-lived and revalidated against the auth server on each request rather than trusted from the cookie. Signing out revokes the session at the auth service instead of only clearing the browser, and it answers to POST alone — a sign-out reachable by GET is a link anyone can make you click. - Five roles, checked in the database. Administering the tenant and holding authority over delivery evidence are deliberately separate grades: the grade that manages membership does not thereby acquire the power to publish evidence, change billing, transfer ownership or delete the tenancy.
- Least privilege is the default state, not a setting. A new member reaches nothing until a membership row places them in one organization at one grade. There is no cross-organization role and no global search: a person with no membership in a workspace gets the same answer from the database as a stranger.
Not held today, and stated plainly because a reviewer will ask. SAML single sign-on is built, and it is activated for no tenant on this deployment — the auth service’s SAML support is switched off at the project level, and no identity-provider connection exists. A workspace can record which verified domain it intends to federate and whether a password should still be accepted for it, but nothing federates today, and the setting that refuses the password route for a federated domain is recorded rather than enforced. Two-step verification for local accounts is built and available to enroll, and is not currently demanded of anybody, so a single credential is what is actually carrying this deployment. Proposed
Where the second factor is checked, precisely. On this application’s own request path, on every request into a workspace, for an account that has enrolled one. It is not checked by the database: the assurance predicate exists and is tested, and it is deliberately not yet applied as a restrictive policy across the register, because the failure mode of getting that wrong is every member of every tenancy locked out at once. The practical consequence is exact and worth stating — a request made directly against the auth service’s data API with a valid single-factor token does not pass through the gate described here. Closing that is a reviewed change of its own. Proposed
Password policy, since it is usually asked about in the same breath. Twelve characters minimum, upper case, lower case and a digit required, and every password is checked against the Have I Been Pwned breach corpus and refused if it appears there. There is no rotation requirement, deliberately: forced rotation is no longer recommended practice and produces worse passwords, not better ones.
The session cookie is deliberately not HttpOnly. The Supabase browser client has to read the session to attach it to its own requests, so the flag cannot simply be set — moving the session behind an HttpOnly cookie is a server-only authentication flow, not a one-line change. Two things carry the weight instead: every workspace and sign-in route is served under a nonce-based script policy that refuses injected inline script, and the tenant boundary lives in the database rather than in the token, so a stolen session still reaches only what that person’s own membership allows.
The decision trail, retention and deletion
LiveEvery act that changes the register’s claims is written to an append-only trail. Deletion is blocked for workspace users, owners and privileged platform roles, and the release proof verifies that boundary by attempting the deletion. Each actor is taken from the authenticated session rather than supplied by the client.
The trail is retained for the life of the tenancy and does not roll off on a fixed short-term schedule.
Procurement scope: read-access logging, scheduled machine-readable exports, certified deletion and litigation hold are not active controls. They can be scoped as enterprise requirements; the page does not represent them as implemented. Proposed
Clinical, payment and personal data
ProposedPortfolio governance does not require protected health information (PHI) or payment-card data. Product fields and import formats are designed for portfolio records, requirements, citations, test outcomes, findings and dispositions.
That scope is a design and contractual boundary, not a technical prevention control. Onboarding acknowledgement, a maintained ingestion boundary and pattern screening for bulk imports are planned, not active.
Enterprise review: confirm data classification, ingestion controls and any required business associate agreement before a regulated-data use case is activated.
Reporting a vulnerability, and incident response
LiveThere is a monitored security mailbox and a published disclosure policy. Both were proved before they were printed: an address that bounces silently turns a researcher trying to help into one who concludes nobody is listening, so the mailbox below was verified end to end with a real message before this page named it.
Security contact: security@theboardwalk.ai — also published machine-readably in security.txt (RFC 9116), which carries the same address, the security page as its policy link, and the scope notes. There is no bug bounty, and the file says so rather than letting a researcher assume one. Tenant isolation is in scope and is the finding we most want.
What is not committed: a notification deadline. Escalation contacts, breach-notification timing and response obligations are defined in the applicable enterprise agreement, and until those operating commitments are executed for a tenancy this page makes no fixed response-time promise. A reviewer who needs “notify within N hours” in writing should raise it in the agreement, not read it into this section. Proposed
Platform operations access
Not heldAuthorized platform operations use an infrastructure-layer credential that can bypass per-tenant policy for service operation and support. Enterprise review should define approved access, logging and break-glass expectations; customer-visible break-glass records and a named system actor are planned. Proposed
Availability, backup and known advisories
Live- Backups. Daily encrypted backups with point-in-time recovery, managed at the database platform layer.
- Dependency posture. Dependency advisories are triaged for reachability. Tests preserve any boundary used to classify an advisory as unreachable, and current dispositions are available during a security review.
What is not committed. There is no published uptime target, no recovery time or recovery point objective, no status page and no disaster-recovery runbook that has been rehearsed end to end. The backups above are a platform feature that is switched on; a commitment about how fast and how recent a restore would be is a contract term, and this deployment has none. Recovery objectives are established in commercial terms for the estate in question. Proposed
Procurement and assurance readiness
Not heldBoardWalk currently provides the implemented control descriptions and dated evidence above for technical review. SOC 2 Type II, HITRUST and FedRAMP authorization are not currently held. Neither is ISO/IEC 27001, and the product is not PCI DSS assessed — it stores no card data, because card details are entered on Stripe’s own page and never reach this application. No independent penetration test report exists to share. There is no third-party audit artifact of any kind: the evidence on this page is our own measurement, run on a schedule, with the date it was taken printed beside it.
Under data-protection law the customer organization is the controller of its register content and BoardWalk is its processor. A data processing agreement, standard contractual clauses, a business associate agreement (BAA), incident notification terms, support commitments and deletion undertakings are negotiated during enterprise review and defined in the executed agreement — they are contract terms, not features already switched on, and this page does not represent any of them as in force. Data residency is the one item on that list we will not contract for today: the regions under Encryption are the ones in use, and there is no EU or UK region to offer.
Directory provisioning (SCIM 2.0) is not implemented. It is named here because every enterprise procurement asks, and because the alternative — joiners and leavers handled by invitation and by an administrator remembering to revoke — is the honest description of what happens today. What it would take is a SCIM endpoint accepting the standard user and group operations against a per-tenant bearer credential, mapped onto the membership grades this page already describes, with a de-provisioning path that revokes rather than deletes so the decision trail survives the person leaving. It is a scoped piece of work, not a research problem, and it is not started.
The platform does not issue compliance assurances; nothing it produces is described as certified.