Skip to content

feat(appkit): define named database operations and policies - #688

Open
ditadi wants to merge 3 commits into
stack/database-stable/01-remove-hooksfrom
stack/database-stable/02-operation-definitions
Open

ditadi wants to merge 3 commits into
stack/database-stable/01-remove-hooksfrom
stack/database-stable/02-operation-definitions

Conversation

@ditadi

@ditadi ditadi commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

What did you change, and why?

Named operations let an app declare who may call each database action. Inputs are explicit contracts: omitting input means no parameters, so a list or count does not need z.object({}) just to disable an inferred { id } input. Outputs are explicit too: omitting output means no body.

  • Adds defineOperation({ name, method, authorize, execute, input?, output? }) and definePolicy to @databricks/appkit/beta.
  • An explicit input schema determines the parsed callback input and the caller's wire input. Without a schema, callbacks receive undefined and OperationWireInput is void, for every method.
  • A callback cannot read input.id, or use a policy requiring parameters, until its operation declares an input schema. Explicit schemas can refine or transform values.
  • Without an output schema an operation answers no body. execute must resolve to nothing, or to null on GET, PATCH, or PUT, and OperationWireOutput is void. Returning a row, a boolean, or null on POST without an output is a type error. A Zod output declares the response and is its public projection.
  • Adds the metadata validator shared by generation and setup: names, reserved names, duplicates, and malformed contracts. An operation without authorization is skipped with a warning naming its file and export.
  • Makes workspace-client type exports explicit so built declarations type-check without skipLibCheck.

Nothing loads or serves an operation in this layer.

Interface

const signedIn = definePolicy({ allow: () => true });

export const countNotes = defineOperation({
  name: "notes.count",
  method: "GET",
  output: z.number(),
  authorize: signedIn,
  execute: ({ db }) => db.notes.count(),
});

export const getNote = defineOperation({
  name: "notes.get",
  method: "GET",
  input: z.object({ id: z.number().int() }),
  output: z.object({ id: z.number(), body: z.string() }),
  authorize: signedIn,
  execute: ({ db, input }) => db.notes.find(input.id),
});

type CountInput = OperationWireInput<typeof countNotes>; // void
// GetNote input: { id: number }; output: { id: number; body: string }, or 404 for null.

definePolicy supports actor/input decisions or a resource lookup followed by an allow decision. The lookup receives the same context as every callback, actor included. Only literal true admits. A resource lookup that returns null or undefined ends the request before allow or execute runs. Definition freezes a descriptor and performs no I/O.

Validation

The definition/metadata tests and type probes pass (17 tests). Probes check explicit inputs, omitted inputs across all methods, incompatible resource policies, omitted outputs (a row, a boolean, or null on POST without output fails), and built public declarations without skipLibCheck. The package build and documentation build pass.

Stack

#683 → #687 → #688 → #689 → #690 → #691 → #692

Design: #683. Previous layer: #687. Next layer: #689.

Review feedback: refactor(appkit): drop entities and default outputs from operation definitions removes entity and the default output types, and documents the actor in policy lookups.


Stack created with GitHub Stacks CLI • Give Feedback 💬

@ditadi
ditadi added this pull request to stack #693 October 23, 2026 15:01
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

📦 Bundle size report

Compared against bundle-size-baseline.json (main).

@databricks/appkit

npm tarball (packed): 1.2 MB (+261 B) — gzipped download (dist + bin; excludes release-only docs/NOTICE).

dist raw gzip
JS (runtime) 1.3 MB (-7.9 KB) 458 KB (-2.0 KB)
Type declarations 473 KB (+8.6 KB) 171 KB (+2.8 KB)
Source maps 2.5 MB (-3.4 KB) 859 KB (+91 B)
Other 11 KB 3.7 KB
Total 4.2 MB (-2.8 KB) 1.5 MB (+958 B)
Per-entry composition (own code — deps external (as shipped))
Entry Initial (gz) Lazy (gz) Total (gz) node_modules (min) Own code (min)
. 106 KB 2.5 KB 109 KB external 344 KB
./beta 102 KB (-879 B) 482 B 103 KB (-879 B) external 307 KB (-3.3 KB)
./testing 45 KB 32 KB 77 KB external 223 KB
./tsdown 520 B 0 B 520 B external 813 B
./type-generator 26 KB 0 B 26 KB external 74 KB

Chunks:

Entry Chunk Load Size (gz)
. index.js initial 102 KB
. utils.js initial 4.6 KB
. remote-tunnel-manager.js lazy 2.5 KB
./beta beta.js initial 82 KB
./beta modular.js initial 6.0 KB
./beta stream-manager.js initial 5.9 KB
./beta service-context.js initial 4.2 KB
./beta databricks.js initial 3.3 KB
./beta client.js initial 647 B
./beta index.js initial 20 B
./beta supervisor-api.js lazy 192 B
./beta databricks.js lazy 176 B
./beta index.js lazy 114 B
./testing manifest.js initial 32 KB
./testing index.js initial 10 KB
./testing wide-event-emitter.js initial 2.9 KB
./testing index.js lazy 28 KB
./testing remote-tunnel-manager.js lazy 2.5 KB
./testing utils.js lazy 1.8 KB
./tsdown index.js initial 520 B
./type-generator index.js initial 26 KB

@databricks/appkit-ui

npm tarball (packed): 395 KB (-2.4 KB) — gzipped download (dist + bin; excludes release-only docs/NOTICE).

dist raw gzip
JS (runtime) 427 KB (-1.9 KB) 146 KB (-774 B)
Type declarations 266 KB (-920 B) 98 KB (-223 B)
Source maps 849 KB (-4.5 KB) 284 KB (-1.4 KB)
CSS 16 KB 3.2 KB
Total 1.5 MB (-7.3 KB) 531 KB (-2.4 KB)
Per-entry composition (consumer bundle — deps bundled, peerDeps external)
Entry Initial (gz) Lazy (gz) Total (gz) node_modules (min) Own code (min)
./js 5.3 KB 49 KB 55 KB 208 KB 14 KB
./js/beta 2.1 KB 0 B 2.1 KB 0 B 5.0 KB
./react 433 KB 49 KB 481 KB 1.3 MB 177 KB
./react/beta 4.7 KB (-199 B) 0 B 4.7 KB (-199 B) 0 B 12 KB (-561 B)

Chunks:

Entry Chunk Load Size (gz)
./js index.js initial 5.2 KB
./js chunk initial 120 B
./js apache-arrow lazy 49 KB
./js/beta beta.js initial 2.1 KB
./react index.js initial 431 KB
./react tslib initial 2.1 KB
./react apache-arrow lazy 49 KB
./react/beta beta.js initial 4.7 KB

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

🤖 AppKit PR bot

🔬 Run evals

Start an eval for this PR from the evals-monitor app: Go to Evals Monitor →

📦 Try this PR's app template

Scaffolds a new app from this PR's SDK build. Run it in any folder (requires the GitHub CLI — gh auth login — and the Databricks CLI):

gh run download 42205549133 -R databricks/appkit -n appkit-template-0.90.0-pr.34587c7-stack-database-stable-02-operation-definitions-688 -D appkit-pr-688 \
  && unzip -o "appkit-pr-688/appkit-template-0.90.0-pr.34587c7-stack-database-stable-02-operation-definitions-688.zip" -d "appkit-pr-688" \
  && databricks apps init --template "appkit-pr-688"

The template pins @databricks/appkit and @databricks/appkit-ui to tarballs built from this branch, so the scaffolded app runs against this PR's code.

ditadi and others added 3 commits November 6, 2026 10:48
Add defineOperation and definePolicy to @databricks/appkit/beta. A

required, unique name identifies each operation, and the entity and

method infer its default input and output. The declaration validator

rejects malformed and duplicate operations and skips those without

authorization. Nothing registers or serves an operation yet.

Signed-off-by: ditadi <victordperd@gmail.com>
Signed-off-by: ditadi <victordperd@gmail.com>
…finitions

defineOperation no longer takes an entity, and an operation without an
output schema types its execute result as void, or null on GET, PATCH, and
PUT for a missing record, instead of inferring a row from a table. The
metadata validator stops checking entities, and the definePolicy and
PolicyContext comments say the resource lookup receives the actor like
every other callback.

Co-authored-by: Isaac <no-reply@databricks.com>
Signed-off-by: ditadi <victordperd@gmail.com>
@ditadi
ditadi force-pushed the stack/database-stable/02-operation-definitions branch from 2f5c59f to ca978b6 Compare November 6, 2026 10:49

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant