Skip to content

Add OpenRouter AI connector#2

Open
rtkzoop wants to merge 91 commits into
feat/zoop-customfrom
feat/ai-integration
Open

Add OpenRouter AI connector#2
rtkzoop wants to merge 91 commits into
feat/zoop-customfrom
feat/ai-integration

Conversation

@rtkzoop

@rtkzoop rtkzoop commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add OpenRouter as an AI connector backed by the OpenAI-compatible API.
  • Register OpenRouter in runtime/admin binaries and frontend connector UI.
  • Add docs, schema/tests, request serialization tests, and connector save tracking.

Test Plan

  • go test ./runtime/drivers/openrouter ./cli/cmd/runtime ./cli/cmd/admin
  • npm run test -- src/features/sources/modal/connector-schemas.spec.ts src/features/connectors/code-utils.spec.ts
  • npm run quality
  • .agents/skills/rill-local-docker/scripts/rill-local-docker.sh rebuild
  • .agents/skills/rill-local-docker/scripts/rill-local-docker.sh validate

rtkzoop and others added 30 commits May 28, 2026 16:58
…yments

Implements §12.1 of the self-hosting plan: a build-time, deployment-wide
gate that hides product surfaces irrelevant to self-hosted Rill Cloud
without forking source.

Shared utility `web-common/src/lib/disabled-features.ts` parses the
comma-separated `RILL_UI_PUBLIC_DISABLED_FEATURES` env var (must use the
`RILL_UI_PUBLIC_` Vite prefix to be exposed to client code) and exposes
`isFeatureDisabled(name)` for consumers. Three features wired:

- `billing`: ORs into `hideBillingSettings` in the org settings nav so
  the "Billing" tab disappears; a new `[organization]/-/settings/billing/
  +layout.ts` throws `error(404)` to keep deep links from working.
- `public-dashboards`: the `ShareDashboardPopover` "Create public URL"
  tab and form now also gate on `!publicDashboardsDisabled`, alongside
  the existing runtime `featureFlags.hidePublicUrl`. The two systems are
  independent - runtime flag still functions for non-Mint deployments.
- `org-creation`: `routes/-/welcome/organization/+page.ts` 307-redirects
  to home before the org-list check, so users without orgs route through
  the standard `OrganizationRedirect` flow instead of the create form.

Dockerfile adds a `RILL_UI_PUBLIC_DISABLED_FEATURES` build-arg (default
empty, so baseline builds stay unchanged). Plan §12.1 rewritten to match
the actual wiring and corrected env var name.

Verified: baseline build (no flags) and full-flag build both succeed; the
env value is baked into the static bundle at the expected call sites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Upstream gates the "Create new project" button on a localStorage flag
`rill:welcome:enabled` that defaults off. For the Mint self-hosted build
this is the primary action on an empty org and there is no alternate
entry point, so users land on a Projects tab with only a "See docs" link.

Invert the default: the flag is on unless explicitly set to "false".
Existing dev-builds that flipped the key on are unaffected; users who
prefer the upstream gating behaviour can still set the key to "false"
per-browser.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Constraint: Keep local browser and worktree runtime artifacts out of future commits.
Rejected: Commit MCP runtime config | contains a bearer token and is unsafe to publish.
Confidence: high
Scope-risk: narrow
Directive: Do not commit .mcp.json until credentials are replaced with environment-variable placeholders.
Tested: git diff --cached --check
Not-tested: Documentation-only planning artifacts were not runtime validated.
Constraint: MCP runtime access needs an Authorization header but repository config must not store bearer tokens.
Rejected: Commit the literal Rill user token | it would expose reusable credentials in git.
Confidence: high
Scope-risk: narrow
Directive: Set RILL_MCP_AUTH_TOKEN in the runtime environment before starting the Rill MCP server.
Tested: python3 -m json.tool .mcp.json; git diff --check; rg secret-pattern scan on .mcp.json
Not-tested: Live MCP connection; requires a valid runtime token in RILL_MCP_AUTH_TOKEN.
Add a dedicated project settings Access page for managing project members, usergroups, and Canvas viewer resource assignments. Reuse the share form through the new access-management component, gate admin assignment actions by permissions, and add unit coverage for project settings navigation and role helpers.
Route org user-management project links to the new Access page and make Admin invite role availability principal-aware so user invites use project-admin permission while usergroup invites require org-admin permission.
Adds a dedicated canvas_viewer role, propagates its permissions through admin APIs and runtime JWTs, and blocks exports, AI, MCP, reports, alerts, and Explore access unless the role matrix grants them.

Constraint: Backend/runtime enforcement is the source of truth; UI hiding is not sufficient for security.
Rejected: UI-only role gating | bypassable via direct API/runtime calls.
Confidence: high
Scope-risk: moderate
Directive: Keep future canvas_viewer changes aligned with docs/plans/2026-05-18-canvas-viewer-rbac.md and the generated proto clients.
Tested: make proto.generate; git diff --check; go test ./admin/database/postgres -count=1; go test -short ./admin/server -count=1; go test -short ./runtime/server -count=1; go test ./runtime/server -run 'TestExport|TestMCP' -count=1; filtered admin/runtime RBAC test set; manual azure-test with developer@zoopsign.com.
Not-tested: npm run check -w web-admin and npm run lint -w web-common are blocked by existing baseline/generated diagnostics.
Wires canvas_viewer permission flags into Access invites, project navigation, route guards, and chat affordances so restricted users see only Canvas-capable surfaces while admins keep existing defaults.

Constraint: Backend/runtime RBAC remains authoritative; frontend gating is defense-in-depth and usability only.
Rejected: Relying on runtime 403s after navigation | causes confusing tabs, deep-link flashes, and broken invite UX.
Confidence: high
Scope-risk: moderate
Directive: Preserve explicit-false permission gating for canvas_viewer while treating omitted flags as granted for backward-compatible clients.
Tested: npm run test:unit -w web-admin -- src/features/projects/project-permissions.spec.ts src/features/projects/project-runtime.spec.ts; npx prettier --check on changed files; git diff --check; npm run check -w web-admin still reports existing baseline diagnostics with no changed-file errors.
Not-tested: Authenticated manual browser pass for the new frontend gates is pending.
Captures the dependency graph, lane ownership, delivered commits, acceptance evidence, and known follow-up boundaries so future reviewers do not have to reconstruct the canvas_viewer rollout from chat or ledger state.

Constraint: The ultragoal asked for a durable artifact in addition to implementation commits.
Rejected: Treating the OMX brief alone as final handoff | it lacks delivered commit IDs and current verification outcomes.
Confidence: high
Scope-risk: narrow
Directive: Keep future canvas_viewer follow-up notes linked back to this artifact and docs/plans/2026-05-18-canvas-viewer-rbac.md.
Tested: git diff --cached --check.
Not-tested: No runtime behavior changed by this documentation-only artifact.
Adds user-facing role guidance so admins understand Canvas viewer is resource-scoped, must be assigned with selected Canvas dashboards, and does not replace broader project roles.

Constraint: CLI resource-scoped assignment is not part of this delivery, so docs point admins to the project Access page instead of claiming unsupported CLI flags.
Rejected: Leaving only the internal implementation plan | admins need the public roles table to explain the new option.
Confidence: high
Scope-risk: narrow
Directive: Update CLI reference separately if resource-scoped project-role assignment is added to CLI commands.
Tested: npx prettier --write on changed docs; git diff --cached --check.
Not-tested: Docs site build not run.
Canvas viewer is only safe when every backend assignment path either carries Canvas resources or rejects the role, and public/force runtime access must preserve the legacy content permissions after the new deny bits exist.

Constraint: Approve access and whitelisted-domain APIs cannot carry resource-scoped Canvas assignments.

Rejected: Allowing canvas_viewer through unscoped access-request or domain-whitelist paths | would bypass backend source-of-truth scoping.

Confidence: high

Scope-risk: narrow

Directive: Any future project-role assignment entrypoint must call validateCanvasViewerResources or explicitly reject canvas_viewer if it cannot carry Canvas resources.

Tested: git diff --check; go test -short ./admin/server -run 'TestListRoles|TestProjectMemberCanvasViewer|TestCanvasViewerRejectedByUnscopedProjectAccessPaths|TestPublicProjectRuntimeTokenGetsContentPermissions' -count=1; go test ./runtime/server -run 'TestExport|TestMCP' -count=1; npm run test:unit -w web-admin -- src/features/projects/user-management/constants.spec.ts src/features/projects/project-permissions.spec.ts src/features/projects/project-runtime.spec.ts

Not-tested: Full repository test suite.
Superuser force-access deployment tokens must bypass the new content deny rules the same way GetProject force access now does, otherwise inspection tokens are minted but unusable for Canvas, Explore, Reports, Alerts, AI, export, and MCP.

Constraint: New read/capability flags drive runtime JWT deny rules and must be synthesized for compatibility paths that bypass normal project membership.

Rejected: Leaving deployment token endpoints to use empty project permissions under SuperuserForceAccess | creates false-deny runtime JWTs.

Confidence: high

Scope-risk: narrow

Directive: Any future force-access token endpoint must normalize content/capability flags before issueRuntimeToken.

Tested: go test -short ./admin/server -run 'TestSuperuserForceAccessDeploymentTokensGetContentPermissions|TestProjectMemberCanvasViewer|TestCanvasViewerRejectedByUnscopedProjectAccessPaths|TestPublicProjectRuntimeTokenGetsContentPermissions|TestListRoles' -count=1

Not-tested: Full repository test suite.
Canvas-only runtime tokens still need ReadAPI for allowed Canvas flows, so custom API endpoints must authorize the API resource before resolver execution and before skip_nested_security can widen nested checks.

Constraint: Built-in APIs are not catalog resources and keep their existing ReadAPI-only behavior.

Rejected: Removing ReadAPI from canvas_viewer tokens | would risk breaking Canvas runtime calls that use API endpoints.

Confidence: high

Scope-risk: narrow

Directive: Any custom API endpoint must apply resource security before resolver execution or OpenAPI exposure.

Tested: git diff --check; go test -short ./admin/server -run 'TestListRoles|TestProjectMemberCanvasViewer|TestCanvasViewerRejectedByUnscopedProjectAccessPaths|TestPublicProjectRuntimeTokenGetsContentPermissions|TestSuperuserForceAccessDeploymentTokensGetContentPermissions' -count=1; go test ./runtime/server -run 'TestCustomAPIRequiresResourceScopedAccess|TestExport|TestMCP' -count=1; npm run test:unit -w web-admin -- src/features/projects/user-management/constants.spec.ts src/features/projects/project-permissions.spec.ts src/features/projects/project-runtime.spec.ts

Not-tested: Full repository test suite.
Centralize invite and edit flows in the Access modal so existing users and groups can be reviewed, updated, or removed from one compact surface. Repair migrated Canvas-viewer rows so local/admin data preserves resource-scoped access.

Constraint: Access management now has one modal surface for invite and edit, and migration 0093 may already have been applied in local databases before the Canvas-viewer repair existed.

Rejected: Keep direct row Remove action | editing needs to expose the current role and Canvas selections before destructive removal.

Confidence: high

Scope-risk: moderate

Directive: Keep Canvas viewer resource-scoped; do not reintroduce blanket project/resource filter unions for Canvas dashboard access.

Tested: go test -short ./admin/server -run 'TestListRoles|TestProjectMemberCanvasViewer|TestProjectMemberCanvasViewerGetsCanvasReadPermission|TestCanvasViewerRejectedByUnscopedProjectAccessPaths' -count=1; go test ./admin/database/postgres -count=1; go test ./runtime/reconcilers -run TestCanvasResolveTransitiveAccess -count=1; npm run test:unit -w web-admin -- src/features/projects/user-management/constants.spec.ts src/features/projects/project-permissions.spec.ts src/features/projects/project-runtime.spec.ts; git diff --check; browser smoke on localhost access page edit and invite modals.

Not-tested: Full web-admin svelte-check remains blocked by existing repo-wide diagnostics outside the changed access files.
Add URL-driven Canvas and Explore tabs in both local and admin shells while preserving existing dashboard state in query params.

Constraint: Dashboard tab selection is encoded only in URL params and must not replace existing filter or time state.

Rejected: Persistent tab state store | URL-only links are shareable and keep route behavior simple.

Confidence: high

Scope-risk: moderate

Directive: Keep DashboardTabs route-shell only; do not move dashboard state ownership into the tab component.

Tested: npx prettier --check changed dashboard tab files

Tested: npm run test -w web-common -- src/features/dashboards/tabs/dashboard-tabs.spec.ts

Tested: npm run test -w web-local -- tests/dashboard-tabs.spec.ts --project=e2e-chrome

Not-tested: Admin cloud route browser flow was not run separately.
Capture the product story and execution plan for persisted dashboard groups so implementation can proceed from explicit resource, RBAC, UI, and test decisions.

Constraint: Dashboard Groups v1 is YAML-authored, runtime-backed, and Canvas-only.

Rejected: Frontend-only URL presets | they would not provide durable listing, validation, or permission semantics.

Confidence: high

Scope-risk: moderate

Directive: Keep grouped access derived from member Canvas permissions unless product explicitly adds group-level grants.

Tested: git diff --cached --check

Not-tested: Markdown docs were not rendered in Docusaurus.
Add dashboard_group resources from proto/parser/reconciler through local and cloud UI routes, including security-aware member filtering so canvas_viewer users only see permitted canvases while full viewers keep all group tabs.

Constraint: Login verification uses localhost:3000 because that origin is whitelisted for Auth0/Google login.

Rejected: Treating groups as ordinary dashboard resources for top-level access checks | canvas_viewer rules can grant member canvas access without granting the group resource itself.

Confidence: high

Scope-risk: broad

Directive: Preserve filtered-member semantics for dashboard_group security; do not reintroduce a pre-filter CanAccess denial for groups.

Tested: go test ./runtime/parser -run 'DashboardGroup|Canvas|Explore' -count=1; go test ./runtime/reconcilers -run 'DashboardGroup|Canvas' -count=1; go test ./runtime/server -run DashboardGroupResourceSecurity -count=1; go test -short ./runtime/server -count=1; go test -short ./admin/server -run canvas_viewer/roles subset; npm run test -w web-common; npm run check -w web-local; npm run test -w web-local -- dashboard-groups.spec.ts; npm run check:edit-route-parity; make proto.generate; browser role checks on localhost:3000 for Google and canvas_viewer users.

Not-tested: Existing broad web-admin typecheck/unit failures remain unrelated; go test -short ./runtime/... still requires external connector env for some packages and has an existing resolver ordering failure.
Canvas-only viewers cannot rely on organization navigation, so the header now renders project and canvas crumbs directly from the project route and runtime resources.

Constraint: canvas_viewer users only have project access, not organization-wide navigation.

Rejected: Reusing full ProjectHeader breadcrumbs | it includes organization-level paths and extra project actions outside the canvas_viewer scope.

Confidence: high

Scope-risk: narrow

Directive: Keep canvas_viewer breadcrumbs project-scoped unless the role gains organization-level access.

Tested: git diff --check; conflict-marker grep; npm run test:unit -w web-admin -- project-permissions.spec.ts; changed-file web-admin svelte-check filter; Vite HMR logs for changed files.

Not-tested: Full web-admin svelte-check remains blocked by existing baseline diagnostics.
Add a repo-local skill and helper script so agents start the Rill cloud dev stack without drifting away from the Auth0-whitelisted localhost ports.

Constraint: Auth flows depend on localhost:3000 for web-admin and localhost:8080 for admin redirects.

Rejected: Relying on ad hoc devtool commands | agents previously accepted alternate Vite ports that break Auth0-sensitive testing.

Confidence: high

Scope-risk: narrow

Directive: Keep 3000 and 8080 fixed for auth-sensitive local validation; free conflicting listeners instead of choosing alternate ports.

Tested: quick_validate.py .agents/skills/rill-local-dev; bash -n rill-local-dev.sh; git diff --cached --check; rill-local-dev.sh preflight; rill-local-dev.sh status after startup.

Not-tested: Fresh clone without Docker already running.
Canvas-only viewers need dashboard groups to appear alongside canvases and show grouped members without duplicating member canvases at the top level. The group page also avoids repeating metadata already represented by tabs and navigation.

Constraint: canvas viewer access depends on runtime ListResources and dashboard-group member specs.

Rejected: hide member canvases only via YAML listing flags | membership should drive grouping automatically for viewer landing pages.

Confidence: high

Scope-risk: narrow

Directive: Keep canvas viewer grouping derived from dashboard_group members so access-filtered runtime results remain the source of truth.

Tested: npx prettier --check changed files; npm run test:unit -w web-admin -- --run src/features/canvas-viewer/selectors.spec.ts; npx eslint changed files; git diff --cached --check

Not-tested: full web-admin check due unrelated existing baseline errors
Keep the forked UI focused on Zoop-Mint by deleting upstream docs, Discord, and Rill support menu entries while preserving logout and restoring the default avatar fallback when profile images fail.

Constraint: Zoop-Mint should not expose upstream Rill community/support links.

Rejected: Brand-name conditional hiding | the running build still showed the items when the brand define did not evaluate as Mint.

Confidence: high

Scope-risk: narrow

Directive: Do not reintroduce upstream Rill support links in Zoop-Mint avatar menus without an explicit product decision.

Tested: npx prettier --write web-admin/src/features/authentication/AvatarButton.svelte web-common/src/features/authentication/LocalAvatarButton.svelte; npx eslint web-admin/src/features/authentication/AvatarButton.svelte web-common/src/features/authentication/LocalAvatarButton.svelte; git diff --check; npm run build -w web-admin; searched built output for removed menu strings.

Not-tested: Browser visual smoke test against a live dev server.
Constraint: PR should not carry the BigQuery gold-dq layer or bundled gold-dq Rill project assets.
Rejected: Keep the sample assets in the branch | user requested removing them from git before the PR proceeds.
Confidence: high
Scope-risk: narrow
Directive: Keep Zoop/RBAC feature changes separate from heavyweight deploy sample artifacts unless explicitly requested.
Tested: git diff --cached --check; verified both target directories are absent from the index and working tree.
Not-tested: full app test suite not run because this change only deletes requested deploy/sample files.
Constraint: PR should not carry the .hermes planning workspace artifacts.
Rejected: Leave .hermes tracked | user requested removing the folder from git as well.
Confidence: high
Scope-risk: narrow
Directive: Keep local planning artifacts out of the Zoop/RBAC feature branch unless explicitly requested.
Tested: git diff --cached --check.
Not-tested: full app test suite not run because this change only deletes requested planning artifacts.
Fix the review findings that blocked the Zoop RBAC/dashboard groups PR: fail open to the normal org page on canvas-summary errors, remove the changed-file lint error, regenerate schema docs, avoid empty dashboard-group loading states, hide tab copy when tabs are hidden, remove deployment-specific MCP config, and restore Pylon identity setup. The docs generator now trims trailing whitespace so generated docs pass git whitespace checks.

Constraint: PR review identified CI blockers and UX regressions that needed to be fixed on the existing feat/rbac-eval branch.
Rejected: Only patch generated markdown manually | make docs.generate would reintroduce trailing whitespace, so the generator needed the whitespace trim.
Rejected: Remove Pylon consumers entirely | remaining billing/help consumers still use Pylon, so restoring identity setup is the minimal safe fix.
Confidence: high
Scope-risk: moderate
Directive: Keep generated docs produced by make docs.generate; do not reintroduce deployment-specific Rill MCP endpoints into repo config.
Tested: make docs.generate; npx prettier --check on changed docs/config/frontend files; npx eslint on changed frontend files; npm run test -w web-common -- src/features/dashboards/tabs/dashboard-tabs.spec.ts src/features/dashboards/listing/dashboard-resource-utils.spec.ts; go test ./cli/cmd/docs; git diff --check.
Not-tested: full web-admin svelte-check remains blocked by existing baseline diagnostics outside the touched files; full e2e suite not run.
The fork's Prettier workflow checks the entire checkout, so local agent/runtime artifacts and binary/unsupported files need to be ignored while changed markdown/Svelte files need to be formatted.

Constraint: zoop/minty-msi CI runs npx prettier --check "**/*" across the repository.
Rejected: Format vendored/local agent skill markdown | these are local agent assets and were explicitly outside the PR review scope.
Confidence: high
Scope-risk: narrow
Directive: Keep local agent/runtime state out of Prettier's repository-wide glob; format changed deploy docs when they are committed.
Tested: npx prettier --check "**/*"; npx eslint on changed Svelte/frontend files; git diff --check.
Not-tested: full e2e suite not run locally.
Move the injected brand constant into ambient declarations, teach ESLint that the Vite define is read-only, avoid generated SvelteKit type imports in route load modules, and give web quality checks enough heap for the combined admin/local/common path. The e2e workflow now skips GCloud auth/setup when the fork does not provide the binary service account secret.

Constraint: zoop/minty-msi CI reported web quality failures and fork-secret GCloud auth failures on the PR branch.
Rejected: Add new TS whitelist entries for the route load files | removing generated  imports avoids the root tsc failure without broadening the whitelist.
Rejected: Keep inline Svelte declare statements | svelte-check rejects declare modifiers inside normal component scripts.
Confidence: high
Scope-risk: moderate
Directive: Keep __RILL_BRAND_NAME__ as a Vite define with ambient workspace declarations; do not reintroduce inline declares in Svelte components.
Tested: FAIL_FAST=false ADMIN=true LOCAL=true COMMON=true bash ./scripts/web-test-code-quality.sh; npx prettier --check "**/*"; npm run test -w web-common -- src/features/dashboards/tabs/dashboard-tabs.spec.ts src/features/dashboards/listing/dashboard-resource-utils.spec.ts; git diff --check.
Not-tested: full e2e tests locally; fork CI must confirm the guarded GCloud path.
Add project RBAC and dashboard group support
rtkzoop added 30 commits June 9, 2026 11:40
Canvas viewer tokens restrict query-filter fields. Allow component-authored filters and chart-internal top-N fields so prebuilt canvas charts can query referenced metrics views without granting arbitrary fields.
Canvas viewer roles can access multiple canvases that share a metrics view. Make chart query-filter allow-lists additive so one canvas does not deny fields required by another.
…nents

feat: horizontal bar charts for canvas dashboards
Extends scatter_plot with viewer-safe reference_lines (static rule layers)
and labels (top-N text layer ranked by the x measure). The labels field is
queried as an extra dimension. Legacy single-layer spec is preserved when
neither extension is configured.
The scatter provider ignored dimension.limit (unlike every other chart
family member), so charts plotted up to 9999 points and outliers squashed
the axis domain. Apply it as a top-N filter ranked by the x measure
descending, matching label ranking, and expose the limit selector in the
inspector.
100% normalized stacked area chart for part-to-whole composition over
time. Mirrors the stacked_bar_normalized precedent: dedicated chart
type wired through the cartesian provider, canvas registry, runtime
validation, reconciler field paths, and the AI chart tool.
…nents

feat(canvas): scatter reference lines/labels + stacked_area_normalized
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