Data inspection
This chapter owns data-specific Workbench behavior. Workbench Layers owns the shared kernel, host and UI boundaries; Tidemark owns the data architecture.
Evidence status: the implementation and deployments below were recorded in September 2026. They are retained as scoped evidence, not rerun production checks on 5 October. Present source, successful tests, deployed backend endpoints and a qualified authenticated desktop journey are distinct. Refresh provider catalogs and authority before relying on earlier observations.
Authority and strict SQL
The agreed authority model is tenant-scoped superadmin: every permission is satisfied within a tenant where that principal has an explicit superadmin grant. Grants on each selected tenant provide access across those tenants and their applications. Newly created tenants need an explicit grant or a reviewed provisioning rule; they do not inherit authority silently.
The Reaktor application and privileged tenant now have stable identities provisioned in production and development. The kernel's operator authority checks this exact application/tenant pair for shared infrastructure; a matching display name is insufficient. Infrastructure operations must carry that authority tenant and a separate concrete target/environment. Reaktor's role grants decide what the operator may request; Kubernetes RBAC, database roles and Cloudflare bindings/tokens still enforce what the executor can do.
The graph-free reaktor-auth-core contains the local authorizer and tenant-superadmin permission override. It preserves tenant, application, audience, resource and principal constraints. The auth server now exposes authenticated /auth/authority/grants and /auth/authority/resolve handlers. Resolution checks the signed user access token, live source session, active identity/principal/membership and current tenant-scoped database grants. It records an audit decision before issuing a short-lived target token, bounded by the source session's remaining validity. It does not copy incoming superadmin claims across applications.
The principal_role.tenant_id migration was rehearsed, checked for idempotence and applied in production and development without removing existing assignments. The updated server was deployed and its unauthenticated authority endpoint returned 401. These changes establish the backend contract; they do not create an operator grant or prove an authenticated desktop journey.
Desktop now has Google authorization-code sign-in with PKCE, nonce/state validation and a loopback callback. Reaktor sessions use an application/environment-scoped credential store; the macOS implementation calls Security.framework directly and was tested against Keychain. Credentials are excluded from workspace state and packages. Other desktop operating systems still need native credential-store implementations. Refresh, logout, grant selection, timeout recovery and cancellation are implemented; local or unknown environments do not silently select remote authentication.
Login, refresh and logout serialize changes to the session. Provider/server cancellation propagates and restores idle state; a failed or cancelled secure-store write clears partial credentials and attempts bounded remote revocation. Regression tests cover overlapping logins and both storage failure paths. The deployed auth server also restricts incoming profile metadata to bounded display fields, preventing older clients from persisting provider tokens or client-supplied authority fields in that profile. The updated server passed rollout health checks and still returns 401 for an unauthenticated authority request.
Still incomplete: packaged desktop sign-in/restart qualification is blocked by local browser callback and Keychain access issues; verified operator grants have not been provisioned. The operator authority handle is not yet wired into native database execution or owning Worker operation admission. Full SQL/Cypher, administrative writes and authenticated agent execution therefore remain unavailable. The current unauthenticated MCP listener remains read-only. A connected database or a deployed authority endpoint must not be described as platform administration.
PostgreSQL offers two explicit modes. Operator read accepts the existing bounded-read-session profile, verifies the login has no elevated role or membership, runs a bounded JDBC read-only transaction, and rolls it back. It reports effective PUBLIC table-write, schema-create and function-execution privileges in the private receipt. It is intended for trusted operator queries: a SQL filter and a session read-only setting are not a security sandbox for untrusted SQL or arbitrary callable functions.
Strict inspector requires least-privilege-inspector-v1. Moving the reader to it needs a reviewed database permission migration or an isolated database or broker; the current state is tracked privately. A Reaktor superadmin grant does not change PostgreSQL permissions. The legacy process adapter continues to require strict mode.
Row-level security is honoured. The reader sees rows only where a reviewed policy allows it, so a new table needs its own grants and a reviewed policy before its rows appear in Hangar. This follows PostgreSQL's default-deny and role-specific policy semantics.
Provider projections
Tidemark defines the target data architecture. The implemented IDE inspects concrete configured providers; it does not implement Tidemark's portable planner or sync engine.
Production is the initial workspace environment. An explicitly selected environment survives restart. Desktop loads the production PostgreSQL connection through the official JVM Kubernetes client and performs bounded connection reads when the workspace opens or its environment changes. The Data navigator shows the selected environment, groups repeated bindings by physical database/bucket/namespace identity, and omits migration files from the connection list. A current successful query updates its admitted source's connection state; restored sensitive receipts do not masquerade as a fresh connection.
Each provider opens an appropriate browser: Tables for PostgreSQL/ClickHouse/D1, Graph explorer for Memgraph, Files for R2, Keys for KV, Instances for Durable Objects, and Topics & subscriptions for Pub/Sub. SQL sources expose Schema, Diagram, Statistics and Query Plan; non-SQL stores omit irrelevant SQL and migration tabs. Reconnect refreshes the selected source. Routine database reads leave their results in the Data workspace without repeatedly opening the execution drawer.
| Provider | Data tab behavior | Boundary |
|---|---|---|
| PostgreSQL | Complete per-table column/PK/FK catalog, readable-table selection, server filters/sort, primary-key seek paging, typed bound parameters, schema graph, JSON EXPLAIN, query timings and database/table statistics; role/RLS/grant/function/trigger/index/activity inspection | Operator and strict profiles remain distinct; SELECT/WITH/VALUES only. Access inspection evaluates catalog grants and policy applicability, without impersonating the selected role or evaluating application JWT predicates |
| ClickHouse | SQL results, query ID, rows/bytes read, server/client timing, EXPLAIN, column/sort/partition metadata and table sizes | Read-only server settings; schema graph has tables without invented foreign keys |
| Memgraph | Registered Cypher inspections, node/relationship graph, property inspection, pagination and EXPLAIN | Free-form Cypher remains disabled until separately verified query authority is integrated |
| D1 | SQL/EXPLAIN for both notification and docs databases; typed private results; schema and size evidence | Catalog broker uses documented per-table PRAGMAs; D1 rejects table-valued PRAGMA queries with SQLITE_AUTH |
| R2 | Real folder prefixes, cursor pages, exact-key metadata, text/binary preview | Preview capped at 1 MiB; larger objects return metadata; page counts are not bucket totals |
| KV | Prefix/key browsing, continuation tokens and bounded exact-key preview | Reads are eventually consistent; listing counts describe the page |
| Durable Objects | Name/ID selection, instance overview, SQLite table catalog and bounded SQL with explain plans/statistics, application-projected state, alarms, connection counts and inspector activity | Binding-only RPCs on owning classes; reachable classes may have no stored record. Recent selections are not namespace-wide discovery. The owning application's state redaction remains in force |
| GCP Pub/Sub | Topic/subscription pages, last-hour Monitoring samples, recent application delivery observations, payload/attribute search, explicit decoders, saved subscription filters and live/pause refresh | Receiver history is bounded and process/isolate-local; filtering applies to the returned page; no pull, ack or seek is performed |
| Device/local ObjectDatabase | Existing connected-device/local SQLite brokers | Requires the corresponding local file, device or simulator; this is distinct from a remote Durable Object |
reaktor.query.v1 receipts carry ordered columns and cells, explicit nulls, provider metrics, plan documents, cursor, query ID, warnings and private errors. Duplicate SQL column names survive. Query statistics distinguish client measurements from server statistics. PostgreSQL JSON plans, ClickHouse text plans, Memgraph plan rows and D1 query-plan trees keep the original provider document alongside operator rendering. A missing statistic is unknown, not zero.
The visible workspace is named Data; the stable database identifiers remain compatible, and desktop --mode=data and --mode=database both select it. Each query document owns an exact target/environment, draft, editor state, browsing state and kernel session. Opening another document against the same source does not overwrite the first document's query or cancel its work. Closing a document cancels its owned session.
Each document retains up to 16 query/schema/plan/statistics records within a 16 MiB serialized payload budget, including repeated runs of the same purpose. History can search receipts, inspect an earlier result or plan, reopen its SQL and parameters, rerun it or pin it. Up to eight completed results can also be pinned within a separate workspace-wide 16 MiB budget. Comparison supports row position or explicit unique keys, duplicate column names, schema differences and null versus missing values. It retains each original result, timing and plan; pins survive document closure and clear when the kernel closes. These receipts remain process-local. Private query/result files are deleted after completion; sensitive history does not enter operational logs or MCP snapshots.
Named SQL statements, focused diagram selections, graph investigations and messaging filters can be explicitly saved in a workspace-scoped, owner-only local library. The kernel owns that service through its graph; it limits the library to 64 entries and 2 MiB, preserves unreadable files, rejects symlink reads and writes atomically. Saved SQL does not include parameter values, results or plan history. The library is not encrypted durable query history. Result grids support numeric sorting without floating-point precision loss, visible-column selection, record and JSON views, and copying the bounded result as CSV or JSON.
Completed query, schema, statistics and plan results can be explicitly exported to CSV or JSON through a native save dialog. The graph-owned kernel export service uses a reusable tooling writer, preserves ordered and duplicate columns, exact string values and NULL, and returns row/byte counts, elapsed time and a SHA-256 digest. Files are bounded to 500 rows, 512 columns and 16 MiB, written through an owner-only temporary file before replacement. This exports the complete bounded receipt, not the currently filtered grid or the entire database. Writer and kernel tests pass; the native save-dialog journey still needs qualification on the unlocked Mac. Parquet, imports and saved column layouts remain unfinished.
The Chart result view supports row, numeric and time axes, up to four numeric series, linked point/table selection and range brushing. Numeric normalization retains exact decimal input; missing values break lines, and time axes accept explicit offsets or UTC dates. Charts show the returned rows with no implicit aggregation. Query documents can refresh every 10, 30 or 60 seconds, with pause and no overlapping runs; changing SQL or bound values pauses refresh. Chart settings and the selected result view survive a refreshed receipt. Plot conversion and Compose pointer/brush interaction tests pass. Split chart comparisons, persisted chart settings and a shared database-monitoring time window remain planned.
PostgreSQL query documents accept ordered JDBC ? placeholders with text, integer, exact decimal, boolean, UUID, date, timestamp and JSON values, including typed NULL. The kernel seals SQL and values together in private storage; the JVM uses a prepared statement. Values are never interpolated into SQL or placed in process argv or operational snapshots. Other providers do not yet accept this parameter contract. Timestamp values require an explicit offset; PostgreSQL's literal question-mark operator uses JDBC's ?? escape.
PostgreSQL plan operators now expose typed row estimates/actuals, loops, inclusive timing, buffers, spills, pruning and parallel fields when the provider supplies them. The tree can collapse branches, show provider attributes, highlight the slowest measured leaf and flag large estimate errors. Per-loop and accumulated values are distinguished; costs never become milliseconds, and nested inclusive durations are not summed into a misleading total. The original provider document and the v1 receipt protocol remain intact.
SQL schema diagrams project returned catalog identities through the existing graph canvas. Search and focus a table, expand incoming or outgoing relationships, undo exploration and explicitly save the selected table set. Selecting a table exposes columns, key flags and defaults; a referenced table outside the returned page is partial. Saved positions, collapsed groups and schema drift comparison remain unfinished. R2, KV, Durable Objects and Pub/Sub use dedicated browsing controls. The Pencil specification includes matching fixture states rather than runtime screenshots disguised as live evidence.
The table browser follows the live catalog. Equality, literal substring, null and numeric comparison filters execute on the database, as does sorting; primary-key columns provide tie breakers when available. Grid search and grid sorting operate on the returned page and remain distinct from server filtering. PostgreSQL uses seek paging when a complete, non-null primary key determines the order; other cases use offsets. Concurrent edits can change either view. PostgreSQL's catalog returns up to 500 complete table records within the receipt payload budget; other catalog adapters retain their row bounds and show truncation. The design draws from DataGrip's data editor, Supabase's table workflow, Memgraph Lab, and Cloudflare's binding RPC model, while retaining Reaktor's shared graph and query receipts.
The PostgreSQL catalog also carries the actual observer role, relation kind, row_security_active and the number of applicable permissive SELECT policies, including inherited-role and PUBLIC applicability. The table navigator and selected-table inspector explicitly explain RLS default-deny instead of presenting zero rows as evidence of an empty table. Existing policies can still filter rows, so a nonzero policy count never becomes an “all rows visible” claim. Missing catalog evidence stays unknown. Views and foreign tables retain unknown underlying RLS semantics instead of inheriting an ordinary table's access claim. These are catalog observations; refresh schema after permission changes.
The local operator profile at tmp/reaktor-operator.json may select googleCredentialFile. It contains a local path, not a credential. The selected profile is included in the reviewed connection definition; changing it requires catalog refresh. Otherwise the kernel checks the explicit operator/Google credential environment and existing local Google configuration. A missing configured credential or an IAM denial is shown as a failure. The GCP account must have Pub/Sub read and Monitoring read permissions; application observations additionally require the existing Reaktor service identity.
Memgraph exploration can load a selected node or its incoming, outgoing or bidirectional neighbours, optionally filtered by relationship type. The JVM accepts only canonical bounded recipes. Observed records merge by internal identity; parallel edges survive, loaded properties are retained, and undo restores the previous exploration. The document limits itself to 32 reads, 1,000 nodes, 2,000 relationships and 4 MiB of current records, with a separate 16 MiB undo budget. Explicitly saved investigations retain read steps, filters, selection and pinned positions; replay obtains fresh records. Internal IDs may be reused after deletion, and combined reads do not claim one atomic database snapshot. Free-form Cypher and graph writes remain unfinished.
R2 and KV also expose a prefix inventory. A kernel-owned read session follows provider cursors, deduplicates keys and groups the observed metadata by prefix. R2 supplies object sizes; KV's list API supplies key and optional expiration metadata, not value sizes or Redis-style memory measurements. A scan is bounded to 10,000 keys, 100 pages, 8 MiB of key names and two minutes. Cancellation preserves partial evidence; a completed listing is still subject to concurrent changes and KV's eventual consistency. The live scan read both configured R2 buckets and KV successfully, while the cursor/cancellation tests preserved partial counts without converting unknown totals to zero.
Durable work inspection
The provider inspectors below are not a general Work dashboard. Queue backlog/DLQ browsing, Workflow instances/steps, authorized redrive, cancel/reconcile controls and applied projection positions require explicit adapters and admission. Display a definition separately from each run and attempt, with exact input/authority revisions and bounded receipts. A successful connection or planned DAG is not evidence of completed work. See Queues and Workflows.
A bounded query or inventory page can be incomplete, filtered by permissions or observed across multiple reads. Record that scope and completeness. No returned rows is not proof that no records exist. Internal Memgraph IDs, R2 cursors and transport message IDs remain provider-local; do not promote them into stable logical entity identity. Data graph evidence defines that boundary.