Constructive Blocks
Use Blocks as the frontend source of truth. Backend presets select database modules, registry roots install frontend source, Console capability discovery proves a public GraphQL shape, and authenticated requests establish effective PostgreSQL/RLS authority. Keep those as separate facts.
Read the pinned contract first
references/install-roots.v1.json is the
portable authority for the exact Blocks branch and commit, release state,
_meta contract, endpoint bindings, package versions, source and built-content
hashes, 19 complete inspector plans, Console runtime invariants, and
structurally scoped source limitations. Use the validated
queries below for ordinary selection; load the full snapshot only when
auditing or updating the contract.
Query the validated catalog instead of loading its entire file when the request concerns an ordinary registry item:
node /absolute/path/to/check-blocks-contract.mjs --list-registry
node /absolute/path/to/check-blocks-contract.mjs --list-registry --type registry:block
node /absolute/path/to/check-blocks-contract.mjs --registry-item app-shell
The 102 entries cover the complete registry: Constructive theme and UI
primitives, app bar, app shell, billing blocks, standalone feature packs,
Console modules, presets, and the Next.js Console Kit. The six non-Data
standalone packs are provider-neutral; Data is adapter-driven and performs
schema discovery through Sheets. Select by name, type,
categories, and docs; inspect one item for its dependencies,
devDependencies, registryDependencies, and files.
Always use the validated queries for Data. The byte-pinned source catalog and
plan retain incorrect generic Data documentation as drift evidence; query
output replaces that field through registry.queryOverrides. Never quote or
implement feature-pack-data documentation by reading the raw catalog or plan
file directly.
Query Console roots and load only the selected complete plan:
node /absolute/path/to/check-blocks-contract.mjs --list-roots
node /absolute/path/to/check-blocks-contract.mjs --root preset-b2b-storage
The query returns a validated portable view of the byte-pinned plan with its
exact dependency closure, file targets, sidecars, corrected registry
documentation, runtime contract, and verification steps. Its
portableContract includes applicable first-party module bindings, referenced
adapter contract and action profiles, the exact standalone pack contract,
current Console store conformance, and _meta when Data is present. It also
returns every sourceLimitations record whose explicit install-root scope
matches the selection. Do not read the inspector v1 generic Data,
single-store, or Organizations-ready sentences in isolation.
Every standalone contract partitions its complete propVocabulary into
requiredProps and optionalProps, identifies deprecated and constrained
props, classifies resource and configuration inputs, and separates controlled,
defaulted, host-resource, host-view, and local state. Use that validated shape
instead of guessing from a component name or a generic feature-pack sentence.
The returned metaContract is executable evidence rather than a version
label: it contains the exact 27-alias type/field requirements plus SHA-256 and
byte-length attestations for META_QUERY_SOURCE and the generated contract
introspection query. Any alias, type, field, or document drift fails the
checker.
Every query returns an installability envelope. While
publicRegistryReady is false, installability.publicInstall and every
item-level publicInstall are blocked and future-only; use only the
envelope's exact pinned local workflow and command template in a disposable
consumer or isolated worktree with the frozen lockfile rule. List queries also
return the current _meta contract and mark each root with a runtimeStatus.
unconditionallyBlocked means a blocker applies in every supported mode;
conditionalBlockers names blockers limited to particular modes.
Standalone Data therefore keeps secure embedded eligible while its
standalone-auth modes are blocked, whereas Console roots containing Data remain
blocked by the nested-store limitation.
references/registry-catalog.v1.json,
references/registry-content.v1.json,
references/package-resolutions.v1.json,
and references/install-plans.v1/ remain the
portable source artifacts behind these deterministic validated queries. The
content snapshot pins every file body reachable from the 19 install plans, so
installed-source evidence cannot be satisfied by a fabricated generated item.
The package snapshot pins the exact npm version, SRI, and canonical tarball URL
for all ten external dependencies; first-party package bytes remain pinned to
the local Blocks artifacts.
Read
references/runtime-contract.md when wiring
standalone Data, Console modules, tenant descriptors, sessions, routing,
capability evidence, or the host-owned Zustand store.
Validate the portable contract from any working directory:
node /absolute/path/to/constructive-skills/.agents/skills/constructive-blocks/scripts/check-blocks-contract.mjs
A fresh pinned checkout does not contain the ignored aggregate registry. Verify its exact commit, clean worktree apart from ignored generated artifacts, canonical source hashes, and release metadata before generating anything:
node /absolute/path/to/constructive-skills/.agents/skills/constructive-blocks/scripts/check-blocks-contract.mjs \
--blocks-repo /absolute/path/to/blocks \
--source-preflight
After the local workflow builds registry and package artifacts, verify every source hash, every planned built-file content hash, and all 19 prebuilt plans:
node /absolute/path/to/constructive-skills/.agents/skills/constructive-blocks/scripts/check-blocks-contract.mjs \
--blocks-repo /absolute/path/to/blocks
The live check deliberately uses the inspector's --no-build mode only after
the aggregate registry, canonical inputs, catalog, and plan bytes match their
SHA-256 attestations. It never rebuilds or edits Blocks.
When advancing the pinned Blocks commit, regenerate the planned content
snapshot from a clean worktree, update its attestation in
install-roots.v1.json, then run the full checker. The generator runs the
pinned build:registry command before hashing any file bodies:
node /absolute/path/to/constructive-skills/.agents/skills/constructive-blocks/scripts/sync-registry-content.mjs \
--blocks-repo /absolute/path/to/blocks
node /absolute/path/to/constructive-skills/.agents/skills/constructive-blocks/scripts/sync-package-resolutions.mjs
The package sync resolves npm's current latest releases. Review every
version/SRI/URL diff, rerun the install and typecheck matrix, then update the
snapshot hash in install-roots.v1.json; never refresh it as an unreviewed
formatting step.
Choose the smallest owning block
For ordinary application UI, choose directly from the complete registry
catalog. app-shell installs the provider-neutral shell and app-bar
transitively; individual billing roots install only their reviewed dependency
closure; primitives remain independently installable.
For feature behavior, choose one ownership boundary:
| Need | Install root |
|---|---|
| Host-controlled application view | feature-pack-{id} |
| Shell/runtime without a leaf feature | console-kit-core |
| Custom tenant console | Selected console-module-{id} roots |
| Stable backend-aligned composition | preset-auth-hardened, preset-b2b-storage, or preset-full |
| Complete seven-pack Next.js console | console-kit-nextjs |
The seven pack IDs are data, auth, users, organizations, storage,
billing, and notifications. A standalone pack never installs Console Kit
and never imposes the Console Kit Zustand store. A matching Console module
installs its standalone view and Console core transitively, then contributes
Constructive discovery, routing, an adapter, and any module-owned state slice.
Map official backend presets exactly:
blank-> no frontend preset root; start withconsole-kit-coreand add only explicitly selected Console modules.auth:hardened->preset-auth-hardened-> Data, Auth, Users.b2b:storage->preset-b2b-storage-> Data, Auth, Users, Organizations, Storage.full->preset-full-> all seven packs.
This mapping selects installed code. It does not prove that a tenant exposes the necessary endpoints, roots, metadata, privileges, or RLS-visible rows.
Respect the branch-only release gate
The pinned source is
feat/feature-packs-console-kit@4f2a789fde9a90c0c6ed5977896493bb4818fa77.
The checkout may be that named branch or detached at the exact commit. Its
publication status is branch-only, and
release.publicRegistryReady is false. Do not run a public install for these
new roots, substitute an older Dashboard registry, or silently select a
similarly named retired block.
Use the executable pinned local-consumption workflow in
references/runtime-contract.md when an
install is required before release. It builds ignored registry/package
artifacts from the attested checkout, serves both local registries, and keeps
consumer configuration explicit. Public installation becomes valid only after
the machine snapshot is deliberately updated to a released commit with
publicRegistryReady: true and the checker passes against it.
For a released registry, preserve the consumer's existing shadcn aliases and configure the canonical namespace:
{
"registries": {
"@constructive": "https://constructive-io.github.io/blocks/r/{name}.json"
}
}
Released query surfaces expose publicInstall with the command beside its
status and availability; execute it only when status is available.
Branch-only responses mark it blocked and future-only, so use the
installability.pinnedLocalConsumption command template instead. Keep shadcn
at 4.13.1; nested dependencies still require the @constructive namespace
when the root is installed by direct URL.
Integrate the installed owner
For Auth, Users, Organizations, Storage, Billing, and Notifications standalone
packs, the host supplies resources, resource states, policy grants, semantic
actions, errors, and selection/view state. Those six views perform no endpoint,
_meta, introspection, session, or capability discovery.
Standalone Data is intentionally different. Its host supplies a resolved data
endpoint plus auth/session transport through SheetsConfig, optionally
injecting SheetsExecuteFn as execute; Sheets then loads Query._meta and
standard GraphQL introspection internally. Data does not own semantic endpoint
selection, Console endpoint fallback, or a
ConstructiveTenantConsoleSession. The top-level
standaloneContracts.data record supersedes the inspector v1 plan's generic
standalone discovery sentence for this one pack.
When auth.mode is standalone, require a non-empty host-resolved
authEndpoint and a databaseId equal to the active tenant before rendering.
The pinned source otherwise falls back to the data endpoint and the shared
default database scope. Standalone Sheets auth also always persists tokens
in localStorage, ignores rememberMe as a persistence choice, and cannot
bootstrap tenant CSRF. Use embedded host authentication for portable installs;
the feature-pack-data root is not unconditionally blocked because
embedded avoids those source paths. Its standalone-auth mode remains
blocked by credential persistence, and standalone-auth-csrf-required is also
blocked by the missing CSRF boundary until Blocks implements both.
For console-kit-nextjs, render ConstructiveConsoleKit from
@/blocks/console-kit/constructive. Pass a secret-free
ConstructiveTenantDatabase containing id, optional name, and explicit
semantic endpoints. Use the installed preset component for a preset root. For
a custom console, render ConstructiveConsoleKitCore with exactly the
installed feature modules and create one host-owned store with every module's
storeSlice. That is the target architecture, but the pinned Data module does
not yet satisfy it: DataFeaturePack mounts SheetsProvider, which creates a
second, nested Zustand store, and dataConsoleModule contributes no
storeSlice. Treat this as a source limitation to remove in Blocks, not a
pattern for new modules.
Keep deployment-specific endpoints and credentials out of installed source. Never derive sibling hosts, invent private routing headers, send tenant database operations through an operator endpoint, or store credentials in Zustand.
Prove static, capability, and authority layers
After installation:
- Select the verification profile. Use
static-registry-installfor ordinary UI and billing registry items; it verifies bytes, dependency closure, typecheck, build, and relevant visual/accessibility behavior but never requires a tenant. Usetenant-runtimefor every feature pack, Console module, preset, core, or full Console root. - Verify installed bytes. Confirm each selected pack wrote
.constructive/feature-packs/{id}.json, plus the preset sidecar for a preset, then run the plan's exact static commands from the consumer root. - Verify host configuration. Resolve every semantic endpoint explicitly
and require a host session's
databaseIdto equal the tenant descriptor. - Verify public capability evidence. Evaluate current
_metacontract2026-07, standard GraphQL introspection, and the exact first-party module bindings inconsoleModuleBindings. Billing uses onlybilling; Notifications uses onlynotifications, regardless of broader optional endpoint candidates in their manifests. The Organizations metadata alternative requirescontract.members, its readable query root, and an executable introspected operation; an organization directory alone must not mark memberships ready. - Verify authenticated behavior. Exercise Auth sign-up, sign-in,
persisted-session restoration, failure handling, and sign-out when Auth is
installed. Supply
csrfTokenProviderwhen the tenant requires CSRF. - Verify RLS. Exercise intended-role CRUD and denied anonymous, peer, revoked, and cross-tenant cases. A visible root or compatible schema does not prove write authority.
Report ready, partial, and unavailable packs independently. Preserve
working packs when another degrades, and keep unsupported controls hidden
instead of fabricating an action or broader authority.
Recover without crossing boundaries
- A 404 root or missing package is a release failure; use the pinned local workflow or wait for release.
- A nested dependency failure usually means the consumer omitted the
@constructivenamespace. - A missing semantic endpoint is host configuration; correct the explicit map rather than deriving another host.
- A database/session mismatch must remain a configuration error.
- Compatible
_metawith a missing executable root requires introspection-led degradation; a runtime authorization rejection requires privilege/RLS diagnosis. - An
objectsendpoint does not prove Storage table capability, and an installed notification backend module does not prove a public inbox. - A Data standalone config without explicit
authEndpointis a configuration error; never allow Sheets to substitute the data endpoint for auth. - An Organizations metadata contract without
contract.membersis unavailable for membership capability even though the pinned discovery module reports it supported. - A host-owned store missing an installed module slice must be recreated with every contribution. Do not introduce another per-feature state system; Data's pinned nested Sheets store is a recorded source limitation.
Do not reintroduce generated SDK requirements, global clients,
BlocksRuntime, flow IDs as install units, credentials in props or
Zustand, process-wide Console stores, or new per-pack Console state systems.