Commit Graph
25 Commits
Author SHA1 Message Date
james.maesandClaude Fable 5.1 f364a3c8de Merge feat/m1-kernel-cli (ee855eb) into feat/m1-process-components
Brings in the extensions, related-records and query-gaps streams. The parity
matrix is regenerated from the merged STATUS table; process downloads already
use the shared safeFileName/saveDownload helpers from the base.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 18:06:15 -05:00
james.maesandClaude Fable 5.1 2bf68e9667 client+cli+dev-idp: OAuth2 browser sign-in with PKCE, provider logout, revoked sign-ins
qqq login --browser signs in with the authorization code and S256 PKCE on a
loopback redirect (RFC 8252): a one-shot listener on 127.0.0.1 takes the
callback, the state is checked, and the code is exchanged at the provider with
the verifier (no nonce, as UI-API-CLIENTS.md section 7 asks). --port,
--redirect-host and --no-open cover exact registered URIs and headless hosts.
A denied request, a forged state or a refused exchange exits 3 and saves
nothing; the new token is checked against the server before it is kept.

qqq logout --provider-logout revokes the refresh token (RFC 7009) and opens
the provider end-session URL with the ID token, which refreshes now keep. A
refresh the provider refuses becomes UNAUTHENTICATED (exit 3, sign in again).

qqq-dev-idp gains the authorize endpoint (Approve/Deny page or auto-approve,
loopback redirects and S256 only), the authorization_code grant, ID tokens,
revocation and end-session. The device flow was run end to end for the first
time against a sample on OAUTH2 (8078) and worked unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 18:02:40 -05:00
james.maesandClaude Fable 5.1 ee855eb146 Merge feat/m1-kernel-cli (extensions) into feat/m1-query-record-gaps
My server findings move to 19 and 20 after the merged 18.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 18:01:43 -05:00
james.maesandClaude Fable 5.1 3c75c22d41 Merge feat/m1-kernel-cli into feat/m1-query-record-gaps
Conflicts resolved by keeping both sides: table get keeps the record view
(sections, links, reveal, help) and gains --join and --variant; create and
update keep uploads and parents and send the variant; filters keep the
DATE_TIME to UTC conversion and accept joined names; export keeps safe
file names. My server findings are renumbered 18 and 19 after the merged
13 to 17. Joined DATE_TIME values are now shown in the local zone too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 18:01:06 -05:00
james.maesandClaude Fable 5.1 6f822f3baa Merge feat/m1-kernel-cli (dd33657) into feat/m1-extensions
Conflicts: core index exports (records, render/files and extensions all kept), CLI context
(imports from both sides; UnsafeFileNameError exits 2 and ExtensionNotInstalledError exits 5),
server-findings (the presence finding is now #18, after related records' #16 and #17). The parity
matrix regenerates unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:58:25 -05:00
james.maesandClaude Fable 5.1 275abe90ca docs: parity rows and TRY-IT line for audits
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:58:06 -05:00
james.maesandClaude Fable 5.1 9cc07008fb docs: parity rows and TRY-IT lines for saved views
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:57:08 -05:00
james.maesandClaude Fable 5.1 dd33657f4f Merge feat/m1-kernel-cli (e058942) into feat/m1-related-records
Brings in the DATE_TIME work (local-zone display and input, --utc, process input exit codes).
The record view now formats DATE_TIME through displayDateTime (the viewer's zone, --utc for
the raw instant, server-zoned text kept), and so do the child lists of table get
--associations and table children; create/update keep the base's conversion through the
form session, including the --parent and --upload paths. process.ts keeps the base's value
formatting with the unified safeFileName/saveDownload. Exports, TRY-IT sections and parity
STATUS merged; this branch's findings renumbered to 16 and 17; matrix regenerated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:57:07 -05:00
james.maesandClaude Fable 5.1 23d625ef9a Merge feat/m1-kernel-cli (e058942) into feat/m1-extensions
Conflicts: core index exports (both kept), CLI context imports (both), main.ts registrations
(extensions and help), server-findings (the presence finding renumbered to #16 after #11-#15).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:56:53 -05:00
james.maesandClaude Fable 5.1 e058942257 core+cli: DATE_TIME typed and shown in the local zone, sent as UTC instants
forms/datetime converts typed wall-clock times (2026-10-31T14:30) to UTC in
the TZ zone with Intl offsets: a time in a spring-forward gap moves forward,
a repeated fall-back time means its first occurrence, and an unchanged
wall-clock time keeps the original instant with its precision. Instants are
shown as 2026-10-31 14:30:00 CDT; display values the server formats in a
declared zone are kept; --utc shows raw instants.

The form session converts DATE_TIME on set (table create, update, copy and
process values), DATE_TIME validation now requires a date and time, --where
and --group criteria on DATE_TIME fields are converted (a date alone is local
midnight), and table get/query and process screens format in the zone.
Tests cover Chicago, London, Sydney and Kolkata DST edges; verified live on
fieldLab (create, get, --utc, TZ=Asia/Tokyo, filters, update across the gap,
fieldLab.bulkEdit values).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:54:29 -05:00
james.maesandClaude Fable 5.1 416790169d Merge feat/m1-kernel-cli (ffedcbb) into feat/m1-related-records
Conflicts resolved: core index keeps every export; table get keeps --key (Go To) and gains
the record view, --associations, --links, --follow, --reveal, --help-content; table export
keeps the new formats, --search and stdout with the kernel's safe default name; README module
table and TRY-IT keep both; server findings keep 11-14 from the base and renumber this
branch's to 15 and 16; parity STATUS merged row by row and the matrix regenerated. The record
view's help helpers are renamed helpEntryText and tableViewHelp, since the base's help and
process screen modules export helpText and tableHelp.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:54:17 -05:00
james.maesandClaude Fable 5.1 8dbd434d8f docs: parity rows and TRY-IT lines for column statistics
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:53:12 -05:00
james.maesandClaude Fable 5.1 e3703a34a1 docs: parity rows, TRY-IT lines and server findings for joins and variants
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:51:25 -05:00
james.maesandClaude Fable 5.1 093b5377fe docs: related records and record view in TRY-IT, parity and findings
TRY-IT gains the related-record and record-view commands as verified against the sample.
Parity: REL-001..005 and 009, REC-028 pass live; REL-006..008, REC-002, REC-029..041 are
partial because the sample declares no such metadata (kernel unit tests cover them).
Findings: downloadRecordFieldFile 500s on a BLOB without adornments, and the sample lacks the
adornment, help and composite-association metadata needed to check those rows live.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:51:00 -05:00
james.maesandClaude Fable 5.1 0ef9bfb364 Merge feat/m1-kernel-cli into feat/m1-process-components
Keeps both export sets in the kernel index, renumbers the process findings to
13 and 14 after the query-gaps findings, and regenerates the parity matrix from
the merged STATUS table.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:49:50 -05:00
james.maesandClaude Fable 5.1 e4916c2971 core+cli: every process step component, review prompt, cancel, back, min/max records
The kernel gains a screen model (process/screen): each step's components in
declared order become neutral blocks both heads render - HELP_TEXT and HTML as
text, VIEW_FORM pairs on every step, RECORD_LIST paged through GET .../records,
the validation review with its preview and summary, PROCESS_SUMMARY_RESULTS
lines, DOWNLOAD_FORM references (GET /download), WIDGET through the widget
render model, and step help content.

The runner presents each screen, asks the provider on every input step
(validation review included), restarts at backStep with isStepBack=true when
the provider returns BACK, cancels on an abort signal with POST .../cancel,
and checks min/max input records before init. A step whose components are
only a VIEW_FORM no longer counts its formFields as inputs.

qqq process run prints intermediate screens to stderr and the last as its
output, asks validate-or-skip and Submit? on a terminal, saves downloads to
--out-dir, and turns Ctrl-C into a server cancel (exit 130). Verified live on
sleepInteractive, greetInteractive, clonePeople, simpleThrow, placeAddressPick
and person.bulkEdit's review screen; findings 11 and 12 recorded.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:47:38 -05:00
james.maesandClaude Fable 5.1 c31a426ea8 docs: parity rows, TRY-IT lines and server findings for query and record gaps (batch 1)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:46:29 -05:00
james.maesandClaude Fable 5.1 2a2325bc6f client: merge every extension document and tag each operation with its extension
The client document is now the sample server's live document (core plus esb, UI API 1.8.0) merged
with the extension documents of every qbit checked out beside this repository: health (qqq), alerts,
assistant, collaboration, data-analysis, db-performance, edi, qa-capture, quick-search,
release-notes, secured-data and sql-workbench. 202 operations, 136 of them from extensions.

- scripts/merge-spec.mjs records each extension's path prefix and operationIds in
  info.x-qqq-extensions, and accepts an extension the core input already carries when its
  operations are identical (the live document's esb), instead of failing on the duplicate.
- scripts/merge-extensions.mjs (npm run spec:merge-extensions) finds the documents, merges them and
  writes openapi/extension-sources.json with each document's version, branch and commit.
- scripts/gen-operations.mjs adds `extension` to OperationInfo (from x-qqq-extensions, else the
  /qbit/{name} or established prefix) and exports DOCUMENT_EXTENSIONS.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:43:58 -05:00
james.maesandClaude Fable 5.1 7f1ad5e120 ci: prepublishOnly and lint scripts the qqq-orb node profile runs
The orb's node_install_dependencies runs npm run prepublishOnly (now the workspace build) and
node_run_tests runs npm test then npm run lint. lint checks license headers and that no
package imports another package's src. Also records finding 10: the sample app has no
uploaded-file archive table, so bulk load cannot be exercised against it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:31:32 -05:00
james.maesandClaude Fable 5.1 455e62ff2f docs: terminal-clients parity matrix generated from the Next UI acceptance matrix
docs/parity/feature-matrix.md keeps the 401 Next UI row ids and adds a CLI and a TUI column
(pass, todo, partial, n/a with reasons), computed by scripts/parity-matrix.py from the copied
Next matrix (docs/parity/next-feature-matrix.md) and the status table in the script. First fill
of the CLI column after the M1 work so far.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:28:49 -05:00
james.maesandClaude Fable 5.1 8ed694cd2f cli: noun-verb grammar on the kernel, output formats, JMESPath, CRUD, api escape hatch
qqq <noun> <verb> for table (list, describe, query, count, get, create, update, delete, export),
process (list, describe, run) and job (list, get, logs, cancel, retry), with the 0.1 flat
commands kept as hidden aliases. Global --output json|table|text|csv|yaml, --json, --query
(JMESPath), --fields, --yes and --trace work before or after the subcommand. Filters take
--where, --group (AND/OR with parentheses), --or, --order, --filter-json, --print-filter and
--count; queries page with --limit, --skip and --all. qqq api <operationId> calls any
operation from the generated index (--path, --param, --body-json, --form, --bytes, --out).
Exit codes: 2 usage and bad filters, 3 auth, 4 unreachable or rate limited, 5 not found,
6 validation, 70 server error. The realtime stream can carry a session cookie for tail.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 17:03:18 -05:00
james.maesandClaude Fable 5.1 ff27af2f9e cli: session sign-in for MOCK and anonymous servers, sent as a cookie; qqq launcher
The client gains getAuthenticationMetaData, createSession (reads the HttpOnly sessionUUID
cookie) and a sessionCookie option; UI_API_VERSION is 1.8.0. qqq login branches on the
server's authentication type and stores a server session for MOCK and FULLY_ANONYMOUS; the
device flow stays for OAUTH2 and AUTH_0. The session goes as a cookie because a bearer
session cannot continue asynchronous process steps on the 4.1.0-SNAPSHOT sample server.
scripts/dev/qqq.sh runs the CLI from source so every commit is testable without a build.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 16:21:02 -05:00
james.maesandClaude Fable 5.1 45db6bbc7e spike(m0): show the running build in the launcher and status line
So the person testing always knows which commit the shell is, and whether it carries
uncommitted changes. TRY-IT.md explains that there is no install step.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 16:17:03 -05:00
james.maesandClaude Fable 5.1 c11495643e spike(m0): OpenTUI feasibility spike with results, dev launchers and TRY-IT guide
Throwaway OpenTUI (React) spike on Bun: 10k x 40 grid, every-field-type form, and a real
UI API process run with an async job against the qqq sample server. Records the go
decision, the measured latencies, binary sizes, and two server findings (bearer session
cannot continue an async process step under MOCK auth; url-encoded process values are
silently ignored). Adds scripts/dev launchers so the client can be tried after every step.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 15:48:34 -05:00
james.maesandClaude Opus 5.5 ea79ddeb78 feat: reference CLI, generated UI API client, conformance suite and dev IdP
- @qrun-io/qqq-ui-api-client: typed client generated (openapi-typescript +
  openapi-fetch) from the merged UI API document; device-flow sign-in, refresh,
  UiApiError (BasicErrorResponseV1), SSE reader
- @qrun-io/qqq-cli: qqq login/whoami/apps/tables/query/get/run/jobs/tail,
  only through /qqq/v1 with Authorization: Bearer
- @qrun-io/qqq-ui-api-conformance: black-box suite + qqq-dev-idp
- scripts/merge-spec.mjs, Prism mock, CI and GitHub Packages publish workflows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 11:47:12 -05:00