Skip to main content

Check access at runtime

Runtime checks are published for Python SDK 0.2.1. They evaluate the authenticated caller configured on the client; do not supply a principal override in application code.

Prerequisites​

  • Configure the Python client for the target app with an authenticated caller.
  • Identify a concrete policy resource such as datatable:orders, an existing record identifier such as order-123, and the proposed attributes for a new record.
  • Choose only actions supported by that resource. For Database, use the resource-action reference.

Check what the caller can do​

Keep existing-record checks separate from create checks. For an existing record, use its real ID and only read, update, or delete. For a proposed create, use ID new, action create, and the attributes that will be submitted. new:i is the batch form, where i identifies each proposed record. new represents the proposed record and must carry the submitted attributes that the create policy evaluates.

The full Database action inventory is read, create, update, and delete. Do not rely on the SDK's default candidate actions because that default includes write, which is not a Database system action.

  1. Place the example in a request path whose configured client represents the authenticated caller.
  2. Replace the resource kind, ID, attributes, and candidate actions with the values reviewed for your policy.
  3. Treat every error as a denial, then test with both an allowed and a denied caller before relying on the result.
import logging

from taruvi import (
AuthenticationError,
AuthorizationError,
ConnectionError,
ResponseError,
ServiceUnavailableError,
TaruviError,
TimeoutError,
ValidationError,
)

logger = logging.getLogger(__name__)

existing_resource = {
"kind": "datatable:orders",
"id": "order-123",
"attr": {"status": "active"},
}
proposed_resource = {
"kind": "datatable:orders",
"id": "new",
"attr": {"status": "draft", "total": 12500},
}
database_actions = ["read", "create", "update", "delete"]
existing_actions = [action for action in database_actions if action != "create"]
create_actions = ["create"]

read_allowed = False
create_allowed = False
visible = []
allowed_actions = []

try:
read_result = client.policy.check_resources([
{"resource": existing_resource, "actions": ["read"]}
])
read_results = read_result.get("results") or []
read_effect = (
(read_results[0].get("actions") or {}).get("read")
if read_results else None
)
# EFFECT_DENY, a missing result, or a missing effect all remain denied.
read_allowed = read_effect == "EFFECT_ALLOW"

create_result = client.policy.check_resources([
{"resource": proposed_resource, "actions": create_actions}
])
create_results = create_result.get("results") or []
create_effect = (
(create_results[0].get("actions") or {}).get("create")
if create_results else None
)
create_allowed = create_effect == "EFFECT_ALLOW"

visible = client.policy.filter_allowed([existing_resource], ["read"])
allowed_actions = client.policy.get_allowed_actions(
existing_resource, existing_actions
)
except (
ValidationError,
AuthenticationError,
AuthorizationError,
ServiceUnavailableError,
TimeoutError,
ConnectionError,
ResponseError,
) as error:
read_allowed = False
create_allowed = False
visible = []
allowed_actions = []
logger.warning("Policy check failed: %s", type(error).__name__)
except TaruviError as error:
read_allowed = False
create_allowed = False
visible = []
allowed_actions = []
logger.warning("Policy check failed: %s", type(error).__name__)

check_resources returns a response dictionary. Each requested action maps to EFFECT_ALLOW or EFFECT_DENY under results[].actions. A missing result or effect must deny. filter_allowed returns only input resources for which every requested action is EFFECT_ALLOW. get_allowed_actions returns allowed names from the explicit existing-record candidate set. A create decision applies only to the proposed new resource and its submitted attributes; it is not a create grant for order-123.

Verification​

The expected result is a caller-bound read decision for order-123, a separate create decision for the proposed new record, a conservatively filtered resource list, and existing-record actions drawn only from the explicit set. On an API, service, timeout, connection, or response error, treat the request as denied. Do not log credentials, personal attributes, raw policy definitions, or tokens.

The JavaScript SDK's policy calls and the Refine accessControlProvider don't work with the current API yet, so use the Python SDK for runtime checks. UI checks such as Refine's CanAccess and useCan only decide what to show; TaruviBase always enforces policies on the server.

Review Security and limits and Troubleshooting before using the decision in a production request path.