Skip to content
Console
Browse documentation
Guide

Share a saved aggregate with a browser page

Review an immutable app-view grant, mint a five-minute browser token on your backend, and stop future access.

On this page

A page you host can read an explicitly approved saved aggregate directly from Anectico. Your backend keeps the management key and mints a temporary app_read token for a signed-in, authorized visitor. The browser receives only that narrow token, in memory. Your agent builds the page and backend in your workspace; you host and operate them.

Ask your agent

Ask your agent to review the project's approved aggregate shares with list_app_view_grants, prepare the complete create_app_view_grant preview, or stop a selected share with revoke_app_view_grant. Your agent uses the existing read and internal-write gateways and the CLI; you review the fixed resources, fields, origins, expiry and external-copy consequence before confirming. The running page and your token-mint backend use REST, with separate credentials as described below.

What the owner approves

An app-view grant fixes one project, one parent management key, exact result IDs with their snapshot IDs and content digests, a closed field projection, the exact source-scope ceiling, exact page origins and a fixed expiry. These fields cannot be edited. Changing one means reviewing a new grant and revoking the old one.

Only a ready saved trend without a breakdown is eligible. Choose one or more closed selectors:

Selector Fields shown
APP_VIEW_PROJECTION_TREND_SERIES_SUMMARY Series IDs, whole-window measurements, contributor and population counts, spans and coverage.
APP_VIEW_PROJECTION_TREND_SERIES_BUCKETS Chart bucket ranges and measurements.
APP_VIEW_PROJECTION_TREND_FORMULAS Formula IDs, operands, units, coverage and values.

The interpretation envelope always includes status, computation and expiry times, measurement windows, coverage, population counts and limits. Definitions, event names, filters, breakdown labels, participant and selection IDs and snapshot details never reach the browser. This recipe grants no persons, logs, transcripts, replay, SQL, execution, writes or SSE access.

An origin is an exact https://host[:port], with no path, wildcard or null. Local loopback HTTP is available only on a development deployment. Approve at most five origins, ten results and three selectors per grant. A grant lasts between five minutes and 90 days, never beyond its parent's expiry; at most 100 active grants exist per project.

Separate discovery, sharing and runtime authority

Step Credential and exact permissions
Builder discovery The usual OAuth connection: docs:read, mcp:read, projects:read, services:read. OAuth does not authorize sharing or minting.
Provision a grant An owner or admin session, or an explicitly delegated management builder, with app_views:share, api_key:read, api_key:write, analytics:read, persons:read and every ceiling and source scope. MCP writes additionally need mcp:write; MCP listing needs mcp:read.
List / revoke Sharing and key-read permission; revoke also needs key-write permission. Reads alone or mint-only authority cannot control grants.
Runtime mint The exact project management key whose ID equals the grant's parent_api_key_id, with app_views:mint, analytics:read, persons:read and every owner-derived source scope. A different key, OAuth session or mint-only key fails.
Measurement preparation Separately authorized analytics credentials: base analytics:read and persons:read, plus source scopes; preview and execution add analytics:query, saved-insight use also insights:read, and full preview inspection adds governance:read. Definition reads need insights:read. The browser token does none of these jobs.

The parent retains ordinary project and domain read authority. Only the issued browser token is projection-restricted. Keep the parent in your backend's secret store, separate from the builder's credential. The closed source ceiling may additionally name groups:read, persons:profile:read and agents:content:read only when the result owner requires them; approve each explicitly.

In Privacy → Content policy, the owner explicitly allows Aggregate result → App-view sharing for the selected project. An ordinary read rule grants no sharing. Missing, unknown or denied consent refuses sharing. Policy changes use that permissioned control and its reviewed confirmation. Set consent before preparing the aggregate. A policy revision can withdraw an earlier publication; prepare an explicitly authorized new result under the current policy instead of reusing an invalidated one.

Read the control contract with anectico api spec --partition customer --out customer-contract.json and the browser protocol with anectico api spec --partition protocol --out browser-contract.json. Pin the serving revision and each artifact's digest. Both are deliberately excluded from the ordinary apps partition; exclusion does not mean their dedicated credential protocol is absent. Inspect get_app_view_grants, post_app_view_grants and delete_app_view_grants_by_grant_id in customer, and post_app_view_grants_by_grant_id_tokens and get_app_views_by_grant_id_results_by_result_id in protocol.

Create a grant file with placeholders for the exact already-measured result:

{
  "parent_api_key_id": "PARENT_KEY_UUID",
  "allowed_operations": ["APP_VIEW_OPERATION_AGGREGATE_RESULT_READ"],
  "resources": [{"result_id": "RESULT_UUID", "snapshot_id": "SNAPSHOT_ID", "content_digest": "EXACT_DECIMAL_DIGEST"}],
  "field_projection": ["APP_VIEW_PROJECTION_TREND_SERIES_SUMMARY"],
  "scope_ceiling": ["analytics:read", "persons:read"],
  "origins": ["https://board.example"],
  "expires_at": "FIXED_RFC3339_EXPIRY"
}
anectico --project PROJECT_UUID app-view grant create --file grant.json --idempotency-key board-share-1
# Review every field, parent authority/expiry, sharing policy, source approval and external-copy consequence.
anectico --project PROJECT_UUID app-view grant create --file grant.json --idempotency-key board-share-1 --confirm-token SERVER_TOKEN
anectico --project PROJECT_UUID app-view grant list --limit 50
anectico --project PROJECT_UUID app-view grant list --limit 50 --cursor OPAQUE_NEXT_CURSOR

MCP has list_app_view_grants through execute_read_action, and confirmed create_app_view_grant / revoke_app_view_grant through execute_internal_action; these add no top-level tool slots. REST controls are GET/POST /api/v1/app-view-grants and DELETE /api/v1/app-view-grants/{grant_id} with exact project and version and the same server preview.

Confirmation binds identical immutable arguments and the complete expected_admission_state_digest shown in preview: current parent authority, sharing-policy version and decision and owner-approved result, snapshot and projection identity and digest. Adapters carry that verified digest automatically; an optional CLI --expected-admission-state-digest can pin it before preview. Even a policy-version change that still allows sharing conflicts and creates no active grant. Review again after a change. Parent facts are fenced at commit; policy and result approval is checked at the immediately preceding verification answer and rechecked by mint and every read. Identical creation retries keep the same creation key and return original metadata, including revoked state, with no new authority or secret.

Mint only on your backend

Mint uses the exact parent key, never a management key supplied by the browser. Your backend signs in its own visitors and authorizes the fixed grant and result it offers. It exposes a fixed token endpoint, never a generic project and path proxy. Set Cache-Control: no-store and prevent token bodies from entering access logs, errors, telemetry or a retained response cache.

The CLI requires a new explicit private file, inside an existing protected directory:

anectico --project PROJECT_UUID app-view token mint --grant GRANT_UUID --result RESULT_UUID \
  --expected-grant-version 1 --expires-at FIXED_FUTURE_EXPIRY --out /private/runtime/browser-token

Stdout contains only nonsecret grant, result, version, expiry and destination metadata. Existing files, symlinks and stdout destinations are refused. The one-time secret is never recovered by listing or retrying. A backend normally exchanges POST /api/v1/app-view-grants/{grant_id}/tokens directly, with project_id, result_id, positive decimal-string expected_grant_version and required expires_at. There is deliberately no MCP token-read action and no human confirmation on each mint.

Expiry must be future, at most five minutes away, and within both the grant's and the parent's current expiry. Tokens are opaque, hash-only, nonrefreshable and audience app_read. A lost mint response requires another bounded mint; no refresh credential exists. Renew only through your authorized backend.

Browser request and refusals

Keep the token only in JavaScript memory. Send Authorization: AppRead <temporary-token> to GET /api/v1/app-views/{grant_id}/results/{result_id} with credentials: 'omit' and no redirects. The browser supplies its exact Origin. No token belongs in a URL, source, DOM, source map, local or session storage, cookie, log, screenshot or retained network evidence.

Preflight admits only GET and the authorization, accept, if-none-match headers. The response allows only the exact approved origin, never ambient cookies or wildcard origins. It exposes the documented validator, retry, rate and budget headers. Every conditional read rechecks access and result lifecycle before returning 304; revoked, expired or erased authority never becomes a cached success.

Render coverage and value states as data. Withheld, unavailable, pending, expired, erased or invalidated results are never measured zero. 401 ends this token's access; 403 refuses the requested origin, resource and projection. Bounded 429 and temporary 503 use their stated Retry-After; stop after a bounded deadline. 501 means the protocol is not configured; 502 means an inconsistent response. Neither is evidence that the aggregate was erased. Hide old numbers on access and lifecycle refusal. A projection has a 1 MiB bound, never a silently truncated answer.

Frozen measurements and replacement

Refreshing grant G1 for result R1 and snapshot S1 preserves that saved measurement after new source data arrives, or truthfully refuses or withholds it under current lifecycle and privacy. It creates no execution. To show a changed measurement, explicitly execute R2 using separately authorized analytics credentials, review a new grant and token for R2, select that result in your app, then revoke G1. Keep result, snapshot and content-digest and execution-row evidence. Never widen G1 or execute on browser refresh.

Ordinary proof links still require the recipient's own Anectico access. A browser token grants none and is never put into a proof URL. Use only a platform-declared result proof link.

Stop access and understand theft

Agents and keys lists every authorized grant through continuation, with exact origins, resources, projection, parent and project, version, expiry and status and observed last use. Missing use or unchecked usage and budget information is explicitly unknown. This accounting identifies the grant and parent, not a verified visitor. Review the server revoke preview and confirm it, or use:

anectico --project PROJECT_UUID app-view grant revoke --grant GRANT_UUID --expected-grant-version 1
anectico --project PROJECT_UUID app-view grant revoke --grant GRANT_UUID --expected-grant-version 1 --confirm-token SERVER_TOKEN

Revoke one grant to stop one share; revoke the parent to stop all its descendants. Policy denial, parent scope removal and expiry, project and workspace deletion and result invalidation also stop future reads. A freeze removes writes and is not a promise that all read access stopped.

A stolen token can read its one approved result and projection until expiry or a current refusal. Origin checks constrain browsers; a nonbrowser thief can forge an Origin header. Revocation and erasure cannot reclaim numbers already displayed, downloaded or copied. You own disposal of your app's caches, logs, exports and external copies.

What your agent hands back

The answer names the parent key's ID and name (never its secret), grant ID and version, result ID, full projection selectors, every exact allowed origin, the token lifetime used (at most five minutes) and the grant's expiry timestamp. It distinguishes sharing authority (app_views:share for the authorized builder) from runtime mint authority (app_views:mint and required reads on that exact parent key). Only the browser token is projection-restricted.

The answer explains expired and revoked access, that owning-result erasure invalidates the share, and which coverage, usage or budget facts remain unknown. It describes the stolen token's limits: the approved origin, result, projection and remaining lifetime, with no mint, execution or write authority. A nonbrowser thief can forge Origin; copied numbers cannot be recalled.

Your agent reports actual local browser checks, control checks and independent value comparisons, and labels any fixtures or untested states. If only the local app ran, it explicitly says that provider or remote deployment and TLS were not run or qualified. A linked verification report supports these facts but does not replace them in the answer.