Skip to content

feat(playground): add files policy test harness#308

Merged
MarioCadenas merged 2 commits intomainfrom
mario/files-policy-playground
Apr 22, 2026
Merged

feat(playground): add files policy test harness#308
MarioCadenas merged 2 commits intomainfrom
mario/files-policy-playground

Conversation

@MarioCadenas
Copy link
Copy Markdown
Collaborator

Summary

Stacks on top of files/service-principal-policies to turn the dev-playground into a live test harness for the new FilePolicy system. Lets us deploy the app and visually verify every policy shape works end-to-end against a real Databricks workspace — something that's hard to prove in unit tests because HTTP routes always run as the SP while policies read x-forwarded-user.

One volume per policy shape, all bound to the same underlying UC volume in app.yaml (policies are evaluated in-process, so the shared physical path is fine):

Volume Policy What it proves
allow_all allowAll() baseline smoke
public_read publicRead() writes → 403
deny_all denyAll() every action → 403
sp_only any(isServicePrincipal, publicRead()) SP bypass via combinator (docs example)
admin_only custom, writes gated on ADMIN_USER_ID custom FilePolicy with real user IDs
write_only not(publicRead()) drop-box shape
implicit (no policy) v0.21 default + startup warning

/policy-matrix page probes every (volume × action) pair against the real HTTP routes and classifies each result as allowed (2xx), allowed* (404 — policy passed, probe file missing), denied (403), or error. A "Run all" button seeds a probe file per volume via upload first, so reads return real content where policy allows writes.

Three server helpers:

  • GET /whoami — echoes x-forwarded-user + admin status (for debugging the auth proxy in the deployed app)
  • GET /policy/sp — programmatic SP-path smoke test, confirms PolicyDeniedError propagates from the SDK (not just HTTP 403)
  • GET /policy/obo — same but via asUser(req), confirms the OBO path sees the user identity and gets denied as expected

Test plan

  • Local: set all seven DATABRICKS_VOLUME_* env vars in apps/dev-playground/.env (all pointing at the same UC volume is fine); pnpm dev; open /policy-matrix; Run all. Expected pattern: deny_all all 403, allow_all all 2xx, write_only reads 403 / writes 2xx, etc.
  • Deploy: pnpm deploy:playground; optionally add ADMIN_USER_ID to app.yaml to exercise the admin path. Verify x-forwarded-user is forwarded by hitting /whoami.
  • /policy/sp returns denied: true with PolicyDeniedError message for deny_all / write_only entries.
  • /policy/obo returns denied: true for deny_all, allowed for public_read.list and sp_only.list.

Base automatically changed from files/service-principal-policies to main April 22, 2026 14:56
Turn the dev-playground's single `default` volume into seven logical
volumes, each exercising one shape of the new `FilePolicy` system:
allow_all, public_read, deny_all, sp_only, admin_only (gated on
ADMIN_USER_ID), write_only, and a policy-less `implicit` volume that
exercises the new publicRead() default plus its startup warning.

All seven keys bind to the same UC volume in app.yaml; policies are
evaluated in-process, so a shared physical path is sufficient.

Adds a `/policy-matrix` page that probes every (volume × action) pair
against the real HTTP routes and classifies each result:
- 2xx        policy passed, op succeeded
- 404        policy passed, probe target missing
- 403        policy denied
- other      error

A "Run all" button seeds a probe file via upload on each volume first,
so reads return real content where policy allows writes.

Also adds three server helpers:
- GET /whoami            echoes x-forwarded-user + admin status
- GET /policy/sp         programmatic SP-path smoke test
- GET /policy/obo        programmatic OBO-path smoke test

Both smoke endpoints confirm PolicyDeniedError propagates from the
SDK path (not just HTTP 403).

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
First deploy of the playground crashed because three env bindings were
missing from app.yaml, causing appkit's runtime resource validation
to fail:

- DATABRICKS_GENIE_SPACE_ID      (genie plugin manifest)
- DATABRICKS_SERVING_ENDPOINT_NAME (serving plugin manifest)
- DATABRICKS_VOLUME_FILES         (files plugin static manifest — kept
                                    alongside the dynamic per-volume
                                    bindings added by the test harness)

Also drops DATABRICKS_VS_INDEX_NAME since the vector-search plugin is
commented out in server/index.ts; binding it made the Databricks Apps
runtime spam "resource vs-index not found" errors.

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
@MarioCadenas MarioCadenas force-pushed the mario/files-policy-playground branch from 87669f6 to 43b2383 Compare April 22, 2026 14:59
@MarioCadenas MarioCadenas enabled auto-merge (squash) April 22, 2026 15:00
@MarioCadenas MarioCadenas merged commit 28155e2 into main Apr 22, 2026
7 checks passed
@MarioCadenas MarioCadenas deleted the mario/files-policy-playground branch April 22, 2026 15:07
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.

2 participants