commits
FTS5 interprets dots as column filter operators, so a query like
"alice.test" was parsed as "search column 'alice' for 'test'" instead
of matching the handle. Adding dot to the escape regex converts it to
"alice test" which matches correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Vite plugin handles import resolution, dev server, and the callXrpc
bridge. Type generation is done by the hatk CLI, not the plugin.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove hatk new scaffolding command (~600 lines) from CLI
- Point users to vp create github:hatk-dev/hatk-template-starter
- Update quickstart with vp prerequisites and new create flow
- Update CLI docs, scaffold docs, project structure docs
- Add pronunciation to site hero
- Disable memory diagnostics logging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Listen for #identity events on the relay and update the handle in
_repos for tracked DIDs when it changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The generated callXrpc client handled 401 responses with a redirect to
re-auth for procedures and queries, but the blob upload path was
missing this handler — causing raw errors instead of graceful re-auth.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rename hero to hat://k, update tagline
- Remove hatk schema CLI command and docs
- Add createReport to API reference
- Update hooks guide to use ctx. style and hooks/ directory
- Simplify mutations guide to callXrpc only
- Remove experimental SvelteKit features section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Double-quote all column names in generated DDL, DML, and FTS queries
to avoid SQLite errors when lexicon field names collide with reserved
words (e.g. "index" from app.bsky.feed.post).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The session's pdsEndpoint was derived from pds_auth_server, but for
bsky.social users the auth server (bsky.social) differs from the data
PDS (e.g. leccinum.us-west.host.bsky.network). XRPC proxy calls were
going to the wrong host, causing immediate InvalidToken errors.
Also handle AT Proto PascalCase error codes (InvalidToken, ExpiredToken)
alongside OAuth snake_case (invalid_token) in the DPoP retry logic.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move inline label definition object to named `labelDefinition` and
`labelLocale` defs so codegen produces reusable TypeScript types.
Adds `locales` array for human-readable label names and descriptions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keeps insertLabels dedup scoped to (src, uri, val) so multiple labelers
can independently label the same content. Adds GROUP BY uri, val to
queryLabelsForUris to collapse duplicates for display.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move com.atproto.repo.strongRef, com.atproto.label.defs, and
com.atproto.moderation.defs from inline objects in lexicon-resolve.ts
to src/lexicons/ JSON files. The resolver now loads all built-in
schemas from disk. createReport lexicon references
com.atproto.repo.strongRef instead of a local #strongRef def.
Build now cleans dist/ before compiling to prevent stale artifacts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move all 14 inlined dev.hatk.* lexicon definitions from cli.ts into
src/lexicons/dev/hatk/*.json. The hatk new command now copies them
with cpSync instead of writing each one inline. Build step copies
lexicons to dist/ alongside templates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SQLite adapter coerces boolean params to 0/1
- pdsCreateRecord and pdsPutRecord now run label rules after local indexing
- clearLabels() added for hot-reload support in server-init
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can submit reports via dev.hatk.createReport XRPC endpoint,
selecting from the app's defined labels with optional free-text reason.
Reports are stored in a new _reports table (dialect-aware for SQLite/DuckDB).
Admins see a Reports tab in the admin UI to review, apply labels, or
dismiss reports. Open report count appears on the Overview dashboard.
Also fixes the label scaffold template to use defineLabel from $hatk,
and adds the createReport lexicon to hatk new scaffolding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move inline template strings from cli.ts into separate .tpl files under
src/templates/ for readability and maintainability. Update xrpc template
with $hatk import and typed query results. Include viewer handle in
ScopeMissing and proxy error responses so the generated client can
preserve identity across re-authentication redirects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wraps existing pds-proxy functions so hooks and XRPC handlers can write
records through the PDS with local indexing, without raw SQL. Also adds
awaitBackfill so ensureRepo properly waits for in-flight backfills.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace HydrateContext with BaseContext (no items field, viewer gains handle)
- Feed hydrate signature: (ctx: BaseContext, items: Row<T>[]) => Promise<unknown[]>
- XrpcContext extends BaseContext, removing duplicate field declarations
- Add buildBaseContext and buildXrpcContext factories, eliminating 4 copy-pasted context constructions across xrpc.ts and opengraph.ts
- Tighten db layer: run/runBatch/all params from any[] to unknown[], typed all<T>() generics at every call site
- FeedContext.db.query tightened to unknown[]
- Codegen updated: BaseContext imports/exports, defineFeed overloads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
searchRecords was returning raw flat rows while all other context methods
(resolve, lookup, getRecords) return shaped Row<T> with .value. Now
search results are reshaped before returning.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract duplicated getRecords logic (fetch by URIs, reshape, return Map)
into a generic getRecordsMap function in db.ts, used by both
HydrateContext and XrpcContext. Adds getRecords to the XrpcContext
interface so XRPC handlers can fetch shaped records by URI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SQLite maps JSON columns to TEXT, so checking col.sqlType === 'JSON'
only worked for DuckDB. This caused reshapeRow and insert operations
to skip JSON parsing/serialization on SQLite.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9 tasks in 5 batches: D1 adapter, Worker entry, Container entry,
build command, integration and docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Worker + Container architecture with D1, Service Binding RPC
for communication, and hatk build --target cloudflare output.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of emitting one log per invalid record during backfill, collect
counts by collection and emit a single validation_skips event per repo.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Assets 404 without /hatk/ base when served from hatk-dev.github.io/hatk/.
Remove this once hatk.dev custom domain is active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deploys VitePress site on pushes to docs/site/** on main.
CNAME configured for hatk.dev custom domain.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Jobs feature doesn't exist yet. Remove generate/destroy job commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Every other define* helper is singular (defineFeed, defineQuery,
defineProcedure, defineHook, defineOG). Align labels to match.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite all documentation to reflect generated client helpers, SQLite-only,
SvelteKit remote commands, and login/logout/parseViewer from $hatk/client.
- Rewrite nav structure with new Frontend section
- Landing page with project tree and feature cards
- Getting Started: quickstart, project structure, configuration rewritten
- Guides: feeds, xrpc handlers, auth (new), seeds, labels, opengraph, hooks
- Frontend: 3 new pages (setup, data-loading, mutations)
- API reference: updated with dual auth (DPoP + cookies), callXrpc
- CLI reference: fixed src/ → app/, localhost → 127.0.0.1
- Remove obsolete: oauth.md, api-client.md, frontend.md, deployment.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a custom fetch function is provided (e.g. SvelteKit's fetch),
bypass the server bridge and use relative URLs so the framework can
deduplicate server/client requests. Guards window.location redirects
for safe server-side execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move login, logout, viewerDid, and parseViewer into the generated
client file so templates don't need a local auth.ts. Layout server
load reduces to a single parseViewer(cookies) call.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single-repo resync now uses triggerAutoBackfill directly instead of
triggering a full network re-enumeration and process restart. Bulk
resync-all still uses onResync callback in production for memory
reclamation restart.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin page failed on SQLite with "unrecognized token: ':''" due to
DuckDB-specific COUNT(*)::INTEGER and pragma_database_size() syntax.
Moved all inline SQL from admin routes into dialect-aware db.ts
functions. Removed unused schema endpoint and UI. Added resync
fallback via triggerAutoBackfill when onResync callback is not provided.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace HMAC-signed cookie with AES-GCM encrypted JSON containing
both DID and handle, using HKDF key derivation
- Remove wrapCallXrpcWithScopeRedirect — no longer needed now that
SvelteKit form actions handle scope errors with redirect() directly
- Simplify getViewer() to sync globalThis read (no more async cookie
parsing or $app/server imports)
- Widen viewer type to { did, handle? } across XrpcContext and handlers
- Extract scopeMissingResponse() helper, replacing 5 duplicate blocks
- Set __hatk_viewer in production SSR path around renderPage
- Add client-side 401 redirect for query endpoints (not just procedures)
- Fix unused import/param lint warnings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BM25 FTS5 already indexes child table text (artist names) and with
incremental FTS the index is always current. The LIKE phases were
scanning 1.7M rows for 12-18s finding nothing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove hatk new scaffolding command (~600 lines) from CLI
- Point users to vp create github:hatk-dev/hatk-template-starter
- Update quickstart with vp prerequisites and new create flow
- Update CLI docs, scaffold docs, project structure docs
- Add pronunciation to site hero
- Disable memory diagnostics logging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rename hero to hat://k, update tagline
- Remove hatk schema CLI command and docs
- Add createReport to API reference
- Update hooks guide to use ctx. style and hooks/ directory
- Simplify mutations guide to callXrpc only
- Remove experimental SvelteKit features section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The session's pdsEndpoint was derived from pds_auth_server, but for
bsky.social users the auth server (bsky.social) differs from the data
PDS (e.g. leccinum.us-west.host.bsky.network). XRPC proxy calls were
going to the wrong host, causing immediate InvalidToken errors.
Also handle AT Proto PascalCase error codes (InvalidToken, ExpiredToken)
alongside OAuth snake_case (invalid_token) in the DPoP retry logic.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move com.atproto.repo.strongRef, com.atproto.label.defs, and
com.atproto.moderation.defs from inline objects in lexicon-resolve.ts
to src/lexicons/ JSON files. The resolver now loads all built-in
schemas from disk. createReport lexicon references
com.atproto.repo.strongRef instead of a local #strongRef def.
Build now cleans dist/ before compiling to prevent stale artifacts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can submit reports via dev.hatk.createReport XRPC endpoint,
selecting from the app's defined labels with optional free-text reason.
Reports are stored in a new _reports table (dialect-aware for SQLite/DuckDB).
Admins see a Reports tab in the admin UI to review, apply labels, or
dismiss reports. Open report count appears on the Overview dashboard.
Also fixes the label scaffold template to use defineLabel from $hatk,
and adds the createReport lexicon to hatk new scaffolding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move inline template strings from cli.ts into separate .tpl files under
src/templates/ for readability and maintainability. Update xrpc template
with $hatk import and typed query results. Include viewer handle in
ScopeMissing and proxy error responses so the generated client can
preserve identity across re-authentication redirects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace HydrateContext with BaseContext (no items field, viewer gains handle)
- Feed hydrate signature: (ctx: BaseContext, items: Row<T>[]) => Promise<unknown[]>
- XrpcContext extends BaseContext, removing duplicate field declarations
- Add buildBaseContext and buildXrpcContext factories, eliminating 4 copy-pasted context constructions across xrpc.ts and opengraph.ts
- Tighten db layer: run/runBatch/all params from any[] to unknown[], typed all<T>() generics at every call site
- FeedContext.db.query tightened to unknown[]
- Codegen updated: BaseContext imports/exports, defineFeed overloads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract duplicated getRecords logic (fetch by URIs, reshape, return Map)
into a generic getRecordsMap function in db.ts, used by both
HydrateContext and XrpcContext. Adds getRecords to the XrpcContext
interface so XRPC handlers can fetch shaped records by URI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite all documentation to reflect generated client helpers, SQLite-only,
SvelteKit remote commands, and login/logout/parseViewer from $hatk/client.
- Rewrite nav structure with new Frontend section
- Landing page with project tree and feature cards
- Getting Started: quickstart, project structure, configuration rewritten
- Guides: feeds, xrpc handlers, auth (new), seeds, labels, opengraph, hooks
- Frontend: 3 new pages (setup, data-loading, mutations)
- API reference: updated with dual auth (DPoP + cookies), callXrpc
- CLI reference: fixed src/ → app/, localhost → 127.0.0.1
- Remove obsolete: oauth.md, api-client.md, frontend.md, deployment.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin page failed on SQLite with "unrecognized token: ':''" due to
DuckDB-specific COUNT(*)::INTEGER and pragma_database_size() syntax.
Moved all inline SQL from admin routes into dialect-aware db.ts
functions. Removed unused schema endpoint and UI. Added resync
fallback via triggerAutoBackfill when onResync callback is not provided.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace HMAC-signed cookie with AES-GCM encrypted JSON containing
both DID and handle, using HKDF key derivation
- Remove wrapCallXrpcWithScopeRedirect — no longer needed now that
SvelteKit form actions handle scope errors with redirect() directly
- Simplify getViewer() to sync globalThis read (no more async cookie
parsing or $app/server imports)
- Widen viewer type to { did, handle? } across XrpcContext and handlers
- Extract scopeMissingResponse() helper, replacing 5 duplicate blocks
- Set __hatk_viewer in production SSR path around renderPage
- Add client-side 401 redirect for query endpoints (not just procedures)
- Fix unused import/param lint warnings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>