Skip to content

Repository files navigation

@gnolith/workshop

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.

Executable

gnolith-workshop serve --config /run/gnolith/workshop.json

The 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-v1

The 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.json

The 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.

Protocol

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.

About

Hosted agent tasks, memories, coordination, and tooling.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages