Public release package
The clean-room contract for the public QueryLayer distribution.
Status: release candidate (MIT); public archive pending clean-room gates
Release status (September 4, 2026). QueryLayer is prepared for public release under the MIT license. The installation path is now the self-contained single-site installer (
scripts/install-site.mjs+install/) documented ininstall.md; no hosted Supabase project or Supabase CLI linkage is required. This is the Advanced (VPS/Docker) path. The proposed universal installation plan adds shared-host ZIP and Vercel + Supabase paths; those remain in development until they pass the plan's acceptance matrix. The clean-room rules below still govern what may enter a public archive: no pilot domains, IDs, credentials, or operator notes.
This document is the clean-room release contract for QueryLayer. It is kept separate from the pilot operator notes so a public checkout never needs the original hosted project, domains, content, credentials, or agent sessions.
#Clean-room installation
The supported installation is documented in
install.md: clone the repository, run the single-site
installer with your own site URL, local administrator credentials, and
installation directory, then verify with the acceptance test. The installer
applies the migrations locally and creates the first local owner — no
external account or project linkage.
The legacy hosted-project flow below still works for contributors who prefer a managed Supabase project for development:
Prerequisites are Node.js 22.12 or newer, Docker, and Supabase CLI 2.115 or newer. Create a new Supabase project (or use a local one), then:
cp .env.example .env
npm ci
supabase link --project-ref <your-project-ref>
supabase db push
npm run check
npm run build
The publishable Supabase URL and key may be used by the browser. Service-role keys, deploy hooks, OAuth credentials, worker tokens, and provider keys belong only in the Supabase server-side secret store. The example file contains placeholders and is not a working pilot configuration.
#Migration-history policy
The private checkout remains the source of truth for environments that already have migrations applied. Applied migration files are never rewritten, deleted, or renamed in place, and a public release never asks an existing private environment to replay a different history.
Each public release is cut from a fresh clean-room database at a declared baseline. The public baseline is materialized by deterministic extraction-time transforms of nine pre-boundary migrations: six transforms remove only their known pilot seed sections, two qualify pgcrypto function calls for the explicit extension schema used by hosted Supabase, and one creates the installer-owned schema that a fresh managed Supabase project does not already have. The reusable schema and function contract remain intact. This is not a single squashed schema dump. The versioned transform chain is self-auditable and re-exportable, and the same chain is applied when the public archive is audited or exported.
Pilot-only migrations stay in the private checkout and remain
export-ignore; they are not part of the public baseline and are not applied
by clean-room installation. The release notes record the baseline migration
version and the private migration head separately so operators can reconcile
history without altering an applied database.
This is a release-archive boundary, not a destructive cleanup: the private checkout retains its complete applied migration history, pilot fixtures, and operator evidence for recovery and upgrade rehearsals.
After the first human signs in, call the authenticated bootstrap_first_site
RPC with the included deployment-neutral helper:
set -a; . ./.env; set +a
read -r -s QUERYLAYER_BOOTSTRAP_ACCESS_TOKEN
export QUERYLAYER_BOOTSTRAP_ACCESS_TOKEN
npm run site:bootstrap -- \
--organization-name "Example Organization" \
--organization-slug example-organization \
--site-name "Example Site" \
--site-slug example-site \
--domain example.com
unset QUERYLAYER_BOOTSTRAP_ACCESS_TOKEN
Press Enter after pasting the token at the silent prompt. The helper reads the token only from process memory and prints organization/site IDs only; the prompt avoids putting the token in shell history. The RPC creates the organization, owner membership, and first site atomically; retrying the same request returns the original IDs. It rejects an identity that already belongs to an organization and never requires direct table inserts or a service-role key.
#Package gate
Run npm run release:check before creating a release artifact. The check is
read-only and verifies required documentation, placeholder configuration,
tracked-file hygiene, migration presence, archive exclusions, and harness
contract coverage. .gitattributes excludes pilot applications, fixtures,
private operator notes, and pilot-only migrations from git archive without
deleting them from the private checkout. To
audit a staged clean-room export, pass its path with --root <directory>.
Use --strict in CI or before publishing; private pilot identifiers, a
missing license decision, or missing package documents fail that gate.
The independently versioned npm packages have a separate, network-free gate:
npm run package-release:check
It validates each public package's metadata, exports, dependency specifiers,
and actual npm pack --dry-run contents, then emits the dependency-safe publish
order. It never creates a tarball or publishes to the registry.
For tooling that needs a stable inventory without parsing the human-readable audit, run:
npm run --silent release:manifest > release-manifest.json
The output is deterministic JSON with format querylayer.release-manifest and
version 1. It contains sorted included paths, sorted ignored paths with
the matching .gitattributes rules, required package/migration coverage, and
path-only security.findings for pilot identifiers or credential-shaped
material. It never emits matched secret values, absolute checkout paths, or
credentials, and it performs no archive, deployment, database, or network
write.
For a deterministic archive audit, run:
npm run release:archive:check
This command resolves the selected Git ref (default HEAD), materializes only
tracked files through git archive, audits that extracted tree in strict mode,
and removes the temporary archive and extraction directory in all outcomes.
It never deploys, publishes, applies migrations, or includes untracked local
files.
After that audit is clean, materialize the exact verified ref into a new directory with:
npm run release:export -- ../querylayer-public
The export is atomic: QueryLayer builds and audits a candidate beside the requested destination, then reveals it only after the strict gate passes. An existing destination is never overwritten, and a failed or interrupted audit leaves no partial public tree behind.
#Decisions required before calling the recovery complete
Select and add an OSI-approved licenseDone: MIT (LICENSE).- Complete the OPS-001 restore and upgrade rehearsals against safe copies.
- Resolve provider activation separately from the core package: Resend, Google/Bing OAuth, deployment credentials, and optional challenge checks.
- Run the clean-room install and record the migration version, checks, and known limitations in the release notes.
Private pilot records under docs/pilots/, private operator procedures, local
environment files, and production identifiers must not be copied into a
public export. The checker reports these rather than deleting them from the
private working repository.