Workshop 0.5 is the self-hosted Gnolith executable. It owns one HTTP listener,
the authenticated /mcp endpoint, authenticated /health/ready, live
/health/live, and the /api/v1/operations/* BFF.
The release is intentionally headless. The former React UI, Site route factories, Worker runtime, stdio transport, and hand-written parallel tool catalog are not part of 0.5.
gnolith-workshop serve --config /run/gnolith/workshop.jsonThe JSON config uses format gnolith-workshop-config-v1, selects exactly one
authentication profile (local-bearer-v1 or remote-oauth-v1), declares an
explicit listener profile, and points to an adapter module that supplies the
Diamond and Taproot public ports. Startup is fail-closed: it does not apply
migrations or bootstrap authorization.
Offline first-owner bootstrap never opens a socket:
gnolith-workshop bootstrap-v1 \
--config /run/gnolith/workshop.json \
--installation-id installation:example \
--base-iri https://example.invalid/ \
--principal principal:owner \
--workspace workspace:default \
--credential-file /run/secrets/workshop-token \
--idempotency-key initial-owner-v1The local bearer credential file must contain exactly 32 random bytes encoded
as unpadded base64url, optionally followed by one LF. The token is never a
command argument and only its domain-separated digest is persisted.
Bootstrap requires Workshop schema version 11 and commits that credential digest
plus an owner receipt through Taproot's sealed owner-adapter API.
For authorization_admin credential-register, callers supply only the
lowercase hexadecimal digest defined in the operation schema:
SHA-256(UTF-8("gnolith-local-bearer-v1\0") || base64urlDecode(token)).
digestLocalBearerCredentialText from @gnolith/workshop/server computes that
value. The operation returns only credential ID metadata; plaintext bearer
material is never returned, persisted, or written to administration audit data.
Offline semantic configuration also runs before the listener:
gnolith-workshop configure-semantics-v1 \
--config /run/gnolith/workshop.json \
--input /run/gnolith/semantic-configuration.jsonThe input contains only declarative provider/vector identities and protected
credential selector IDs. It never contains credential bytes. Configuration can
be persisted while unavailable; gnolith_status.semanticState.ready becomes
true only after the selected generation is actually ready, while lexical search
remains available. provider.endpoint is the exact POST URL: an
OpenAI-compatible endpoint ends in /embeddings (for example
https://provider.example/v1/embeddings) and an Ollama-compatible endpoint
ends in /api/embed. A configured but degraded semantic provider makes
/health/ready return 503 without preventing the process from starting or
serving lexical search.
gnolith_status.semanticState.diagnostic is either null or the exact
secret-safe gnolith-workshop-semantic-diagnostic-v1 object. The versioned
object reports only a bounded code, retryability, sqlite|qdrant backend, and
the bounded retry repair class. It never includes URLs, credential selectors,
paths, provider messages, or recursive causes. Exact downstream fixtures are
published at schemas/fixtures/workshop-status-evidence-v1.json.
Authorization visibility uses canonical CNF. The clauses array is ANDed,
while atoms inside one clause are ORed. Owner-or-reader is one clause containing
both principal atoms. Two singleton clauses mean owner-and-reader and are
rejected when the administering principal cannot satisfy the resulting scope.
Verified Waystone assets should use the exported /app mount recommendation.
The root, /mcp, /health, /api, and /.well-known namespaces cannot be
used or shadowed by an asset mount. The Node listener rejects encoded dot
segments and encoded path separators before URL normalization.
Local resource payload backup and restore use the public server-only factory:
import { createLocalFilesystemResourceBlobPortsV1 } from '@gnolith/workshop/backup';
const blobs = await createLocalFilesystemResourceBlobPortsV1({
root: '/var/lib/gnolith/blobs',
});The returned backup and restore ports accept only Taproot descriptors,
streams, stage IDs, and opaque reference IDs. Filesystem layout remains private
to Workshop.
Whole-owner restore uses createWorkshopBackupApi from the same export.
Orchestrators pass the opaque document back to importBackup; Workshop
canonicalizes logical records, atomically replaces only the bound
installation's owner state, and rejects inconsistent duplicates.
The sole MCP identity is gnolith. The generated operation contract contains
exactly 52 versioned operations and is checked into
schemas/gnolith-operations-v1.json. The same generated registry drives MCP,
the BFF, runtime validation, and the generic browser-safe client:
import { createWorkshopClient } from '@gnolith/workshop/client';
const client = createWorkshopClient({
baseOrigin: 'https://gnolith.example',
accessToken: async () => obtainAccessToken(),
});
const status = await client.call('gnolith_status', {});See the architecture-reset guide for deployment, authentication, migration, lease, backup, and compatibility details.