KDCube
← Recipes
KDCube Recipes · The Steel Rule

Change Who Can Reach Your KDCube App Without Rebuilding

Declare stable API, MCP, and widget surfaces in code. Change availability, audience, authority, and browser request proof per deployment.

31.07.2026app surface governance
app surfaces API policy MCP governance deployment configuration KDCube surface governance API roles and visibility bundle operation CSRF

WHAT LEAVES THE SHOP

Your app keeps portable surface defaults in code, while each deployment can switch a resource off, narrow its audience, select an authority, or require one-time browser CSRF proof without rebuilding it.

KDCube calls the deployable unit an app in builder-facing prose. Literal SDK and descriptor contracts still say bundle in names such as @bundle_entrypoint, bundle_id, and bundles.yaml.

YOU WILL NEED
  • an app with an API, MCP, or widget declaration
  • its item in bundles.yaml
  • the Control Plane Apps view or descriptor source
  • one permitted and one denied test identity
  • a real caller for the surface you change

10OPSeparate Existence From Policy

Keep five questions independent. One private switch cannot express all of them.

QuestionOwnerResult
Does it exist?code decoratorUndeclared code is not remotely callable through that surface family.
Is it active here?enabled.*A disabled app or resource returns 404.
Who may reach it?visibilityUser-type and raw-role checks run before app code.
Which authority may call?authCurrent or delegated authority and grants are checked.
Does a cookie mutation carry request proof?API csrfA one-time token proves intent for the exact operation POST.

enabled is availability. visibility is audience policy. auth is authority policy. csrf is request proof, not another role or grant.

App surface declaration and deployment governance API, MCP, and widget declarations enter separate deployment policy lanes before meeting request-time enforcement. API policy includes enabled state, visibility, authority, and optional operation POST CSRF. MCP policy includes enabled state, transport, and authentication. Widget policy includes enabled state, visibility, and authentication. APP SURFACE CONTROL STACK Declare once. Govern each deployment. Enforce every request. CODE DECLARATION DEPLOYMENT POLICY EFFECTIVE GATE API @api(...) method · route · safe defaults API METHOD POLICY enabled · visibility · auth · csrf route + alias + METHOD, with code fallback MCP @mcp(...) route · transport · auth MCP ENDPOINT POLICY enabled · transport · auth public, app-owned, or managed authority WIDGET @ui_widget(...) alias · audience defaults WIDGET POLICY enabled · visibility · auth user types, raw roles, optional authority REQUEST TIME effective gate available? visible and authorized? request proof valid? ONE DECLARATION · ONE DEPLOYMENT POLICY · ONE ENFORCED RESULT
One declaration, a deployment policy, then the effective request gate.
INSPECT

Name separately what would make one surface absent, hidden, unauthorized, or rejected for missing browser request proof.

20OPDeclare Portable API Defaults

Put the operation and its safe defaults on @api(...).

entrypoint.pyPYTHON
from typing import Any
from kdcube_ai_app.infra.plugin.bundle_loader import api

@api(
    method="POST",
    alias="report_publish",
    route="operations",
    user_types=("registered",),
    roles=("kdcube:role:editor",),
    csrf=True,
)
async def report_publish(self, **payload: Any) -> dict[str, Any]:
    return await self.reports.publish(payload)

Both visibility dimensions apply when both are present. user_types use anonymous < registered < paid < privileged. roles compare raw role ids.

csrf=True is valid only for POST on operations. Public webhooks use provider proof or another configured guard.

INSPECT

App discovery lists report_publish [POST] operations with the decorator's effective audience and CSRF default.

30OPOverride The Exact API Method

Write only the deployment difference under the concrete route, alias, and method.

bundles.yamlYAML
bundles:
  items:
    - id: reporting@1-0
      config:
        surfaces:
          as_provider:
            api:
              operations:
                report_publish:
                  POST:
                    visibility:
                      user_types: [registered]
                      roles: [kdcube:role:publisher]
                    auth:
                      authority_id: platform
                      grants: [reports:publish]
                    csrf: true

Resolution: method policy wins over alias fallback; alias fallback wins over the decorator default.

A missing value keeps the code default. An explicit empty visibility list removes that restriction for this deployment. Keep descriptors sparse so they do not pin every old code default.

INSPECT

The effective API descriptor reports the effective value, code default, exact descriptor path, and whether an override exists.

40OPSwitch One Resource Off

bundles.yaml · configYAML
enabled:
  bundle: true
  api:
    "operations.report_publish.POST": false
  mcp:
    reports: true
  widget:
    reporting: true

Missing values mean enabled. This is an override layer, not a second inventory of app resources.

INSPECT

Disable report_publish: it returns 404, while a sibling API, MCP server, or widget remains available.

50OPUse The Apps View

Open Apps, select the app, then select the concrete API, MCP endpoint, or widget. The editor writes the same descriptor-backed paths.

For an API POST on operations, Cookie request CSRF shows the effective value, decorator default, exact descriptor path, and explicit-override state. Save writes the method override. Reset writes a null marker there and restores the decorator default for that method.

The MCP editor has no CSRF switch. MCP uses explicit protocol credentials and its own auth contract, not ambient browser cookies.

INSPECT

Save one local override, reopen the resource, and see its marker. Reset it and see the decorator default return.

60OPTeach The Browser The CSRF Exchange

When the effective API policy has csrf: true, a cookie-authenticated browser obtains one token before the mutation.

browser request sequenceHTTP
GET  .../operations/report_publish/csrf
  -> {csrf_required: true, csrf_token: "...", expires_in: 600}

POST .../operations/report_publish
X-KDCube-CSRF-Token: <returned token>

The token binds subject, tenant, project, app, operation, and method, then is consumed once. Missing, expired, reused, or mismatched proof gets 403. Shared proof-state unavailability gets 503.

Explicit bearer and ID-token requests do not perform this cookie exchange. Their credential is non-ambient request proof; visibility, authority, grants, and product authorization still run.

INSPECT

POST without a token returns 403; a fresh token reaches the operation; token reuse returns 403.

70OPUse Each Surface's Vocabulary

SurfaceDeployment controls
APIenabled; user types; roles; authority/grants; operation-POST CSRF
MCPenabled; transport; public, app-owned, or managed auth
Widgetenabled; user types; roles; optional authority/grants
App listingenabled.bundle; app-level allowed_roles

@mcp(...) intentionally has no proc-side user types, roles, or CSRF. Govern a protected MCP endpoint through its auth owner.

bundles.yaml · managed MCPYAML
surfaces:
  as_provider:
    mcp:
      reports:
        auth:
          mode: managed
          authority_id: delegated_client
          tools:
            report_read:
              grants: [reports:read]
            report_publish:
              grants: [reports:publish]
          selected_tool_grants: true

Managed mode checks the delegated bearer, concrete resource, selected tool, and grants before app MCP code runs. Bundle mode leaves credential verification to the app.

INSPECT

Discover the MCP endpoint, then call one permitted and one denied tool through the selected auth mode.

80OPVerify The Effective Deployment

  • Reload the app or wait for the live property update.
  • Reopen Apps and inspect effective values and override markers.
  • Test a permitted and denied user/role independently.
  • Test authority/grant denial independently from visibility.
  • Test CSRF missing, accepted, and reused states when enabled.
  • Run MCP discovery and one real tool call.
  • Disable one surface and verify siblings remain live.
  • Reset one override and verify the code default returns.

For local source changes, refresh or reload the staged runtime copy before judging the result.

FINAL INSPECTION · DONE MEANS
  • Code declares every real surface and its portable defaults.
  • Descriptors contain only intentional deployment differences.
  • Availability, audience, authority, and request proof remain separate.
  • API policy is route- and method-specific where needed.
  • Protected cookie POSTs implement the token exchange.
  • MCP uses MCP auth rather than API CSRF or role shortcuts.
  • Reset restores the decorator default.
  • The effective behavior passed a real transport test.

Documentation

Related articles