---
name: applicaster-context-setter
description: "Get Context API integration: use when building or hardening a customer-hosted backend for the Applicaster Context Setter Plugin — the GET endpoint(s) that populate storage_keys and, for authenticated/account-scoped data, persistent_keys. Works in any stack; establishes Remote-URL-only or Remote+Runtime scope, resolves per-namespace ownership, business-logic source, persistence and scope, and auth/delivery before edits, validates request AND response boundaries through the project's own validator, and ships a skill-local contract-driven context-setter-e2e tool that validates a running service against an approved contract."
---

# applicaster-context-setter

Implement or harden a customer-hosted **Get Context API** — the backend the Applicaster
Context Setter Plugin fetches to populate `storage_keys` and, for Runtime URLs,
`persistent_keys`. The deliverable is endpoint(s) that satisfy the documented wire
contract, with validation on **both** the request/auth boundary and the response
boundary, plus an executable proof via the skill-local
[context-setter-e2e tool](tools/context-setter-e2e/README.md).

This is a **backend/API** skill, not a plugin implementation: it never mutates Zapp
Studio. It supports the mandatory **Remote URL** (fetched once at app init, `storage_keys`
only) and the optional **Runtime URL** (fetched post-init, `storage_keys` **and/or**
`persistent_keys`, optionally synchronized to login/logout via `observe_storage`). Which
namespaces, keys, business logic, and scope apply are entirely project-specific — this
skill fixes only the plugin's wire shape and asks the developer to resolve everything
else. See [context-setter-contract.md](references/context-setter-contract.md).

## Scope

- Use for a new or existing backend that must expose a Get Context API — a Remote URL
  always, a Runtime URL when explicitly selected, and authenticated user-context
  synchronization (`observe_storage` + logout purge) as a further optional branch of
  Runtime.
- **Adapt to the target project's stack** — language, framework, package manager,
  validation library, HTTP client, test runner, config/secrets, and deployment
  conventions. Do not assume a JavaScript implementation, and do not add a validation
  dependency the project lacks a use for; use its existing tools.
- Do not invent an upstream persistence layer, a new context key, or namespace/key names.
  Reuse the project's existing sources (static config, an existing API/provider, existing
  business logic) and existing Endpoint/context-key conventions.
- The wire contract is fixed and documented. Confirm live docs; do not invent response
  fields, scopes other than `user_account`, or status codes.

## Non-Negotiable Gates

1. Every accepted request input (query param/header) and every credential is validated
   before use, and every response is validated against the versioned `v1` shape before it
   is returned, using the target project's own validator. A request-only integration is
   incomplete — the response check is what stops a malformed body reaching the plugin. See
   [validation-patterns.md](references/validation-patterns.md).
2. `version: 1` is always returned. A Remote response returns `storage_keys` and never
   `persistent_keys`. A Runtime response may return `storage_keys` and/or
   `persistent_keys`; when present, `persistent_keys.content` is required and
   `persistent_keys.scope`, if present, is exactly `"user_account"`. Namespaces/keys are
   non-empty strings; unknown top-level fields are rejected.
3. Each endpoint returns only the namespaces/keys it is the agreed owner of (the ownership
   ledger resolved with the developer). Never write to a namespace another integration
   (another Context Setter URL, the Login Flow plugin, etc.) already owns.
4. Never invent a context key. Resolve every accepted credential/context key from the
   project's existing Endpoint configuration or
   [available-context-keys.md](../applicaster-dsp-content-feeds/references/available-context-keys.md);
   ask the developer when neither establishes it.
5. Default every response to `Cache-Control: no-store`. Only an explicitly developer-approved,
   public, deployment-level Remote response may use a project-native caching rule — never a
   Runtime response or anything touching `user_account`-scoped data.
6. When the user-context synchronization scenario is in scope, the Runtime URL must return
   the declared account-scoped keys as explicit `null` values when the credential is
   absent/invalid (the logged-out state), not merely omit them.
7. Do not claim end-to-end validation without a successful `context-setter-e2e` run against
   a running service and its approved contract, or a concrete blocker for a missing
   runnable URL, credential, or safe test data.
8. Do not finish without a `## Zapp Configuration` handoff. Create a persistent
   `zapp-context-setter-configuration.md` beside the target project's README by default for
   deployable work; the developer may decline it, and it is skipped automatically for
   explicitly throwaway/mock-only work.

## 1. Establish facts

1. Fetch the current Get Context API, Endpoints and Context Keys, and Available Context
   Keys documentation. Read [context-setter-contract.md](references/context-setter-contract.md)
   alongside it and reconcile any drift toward the live docs. If a live source cannot be
   fetched, name it and ask whether to proceed from the bundled snapshot — never silently
   treat it as current.
2. Inspect the target project without asking: existing route/handler conventions, request
   validation and test conventions, existing Endpoint/context-key configuration and
   available auth mechanisms, config/secrets convention, deployment URL shape, and any
   existing Get Context, Context Setter, or related storage/persistence code. Search for an
   existing namespace ownership convention (e.g. what the Login Flow plugin or other
   integrations already store) before proposing new namespaces.
3. For an existing integration, inventory its routes, consumers, tests, and currently
   returned namespaces/keys. Treat a changed response shape, namespace ownership, auth
   mechanism, or Studio Endpoint configuration as a compatibility impact.

Completion: evidence the stack, existing behavior, existing namespace ownership, and
live-contract reconciliation in a concise sourced fact summary.

## 2. Resolve developer decisions

Ask only for facts the project and documentation cannot establish. Ask one question at a
time, including the discovered constraint, a recommendation, and the consequence of
choosing otherwise. Use [decision-guidance.md](references/decision-guidance.md) for the
complete branch rules. Resolve in this dependency order:

1. **Remote-only, or Remote + Runtime?** Remote is always in scope; Runtime must be
   explicitly selected.
2. **Is the user-context synchronization scenario in scope?** (Runtime + `observe_storage`
   + logout-purge via explicit `null`s.) Only relevant when Runtime is selected.
3. For **each** selected URL: the request context-key/delivery mechanism, any accepted
   query params/headers (only ones the project already has a convention for), the
   business-logic source for every namespace/key it returns, and the namespace/key
   ownership ledger (confirm no other integration already owns them).
4. For **each** namespace: `storage_keys` (session-only) vs `persistent_keys` (survives
   restart), and if persistent, unscoped (app-wide, survives logout) vs `scope:
   "user_account"` (cleared on logout).
5. For a protected Runtime URL: the auth/delivery mechanism — prefer Bearer
   `quick-brick-login-flow.access_token` via the Endpoint's Bearer/header configuration;
   use `ctx` only when multiple context values are needed in one request.
6. Cache-policy exception approval — default `no-store`; approve an override only for an
   explicitly public, deployment-level Remote response.
7. Route reuse — whether Remote and Runtime can share the existing project route/handler,
   or must split because auth, data source, or lifecycle differ materially.
8. The target project's response-validation convention and the runnable
   `context-setter-e2e` inputs: URL(s), credential, and the exact namespaces/keys/scope
   expected per scenario, including any `unauthenticatedError` and `logout` assertions.

Completion: every applicable decision has a recorded developer answer, including the full
per-namespace ownership/persistence/scope ledger.

## 3. Confirm before edits

Present a short implementation contract and wait for explicit approval. Include:

- Selected scope (Remote-only, or Remote + Runtime, and whether user-context
  synchronization is in scope).
- Each URL, its route/handler, auth/delivery mechanism, and any accepted request inputs.
- The full namespace/key ledger: owner, storage type (`storage_keys` vs `persistent_keys`),
  scope (`user_account` or unscoped), business-logic source, and — for
  `user_account`-scoped keys — the logout-purge behavior.
- Cache policy per URL.
- Target-project validator, changed files, and compatibility impact.
- The exact `context-setter-e2e` contract and command, or the specific missing
  prerequisite.
- Whether to create or update `zapp-context-setter-configuration.md`.

Refresh the contract if a material decision changes later.

## 4. Implement the contract

1. Implement or verify the Remote route and, if selected, the Runtime route (or shared
   route per the route-reuse decision) using existing project patterns.
2. Validate every accepted request input and credential before use; apply the agreed error
   mapping (`400` for invalid/unknown input, `401` for a missing/invalid Runtime
   credential), never logging the raw credential, decoded `ctx`, or context values.
3. Build each namespace/key from its agreed source. Return only the namespaces/keys the
   route owns.
4. Render the response, validate it against the `v1` profile (Remote:
   `storage_keys` required, `persistent_keys` forbidden; Runtime: either/both allowed,
   `persistent_keys.content` required when present, `scope` exactly `"user_account"` when
   present) and the namespace-ownership ledger, then set `Cache-Control: no-store` (or the
   approved exception) and return it. On validation failure, log sanitized diagnostics and
   return a safe `5xx` — never a malformed body.
5. When the user-context synchronization scenario is in scope, return the declared
   `user_account`-scoped keys as explicit `null` when the credential is absent/invalid, and
   configure the corresponding Endpoint with the `observe_storage` tag (recorded in the
   Zapp Configuration handoff, not applied by this skill).
6. Make only the necessary changes. Keep secrets/config in the project's existing
   convention; never log tokens, `ctx`, or decoded context.

Completion: every implemented route validates both boundaries, returns only its owned
namespaces/keys, and matches the approved contract.

## 5. Verify and hand off

1. Run the target formatter, typecheck, and relevant endpoint tests.
2. Define a versioned `context-setter.contract.json` (see
   [templates/README.md](templates/README.md) for the two starting shapes — remote-only,
   and runtime with a `user_account` namespace) that declares every selected scenario's
   URL, `mode`, auth, and expected namespaces/keys/scope, plus any
   `unauthenticatedError` and `logout` assertions. Run the bundled
   [context-setter-e2e](tools/context-setter-e2e/README.md) CLI with `--contract`, the
   required safe test credential, and a sanitized `--json-report`. It rejects a
   schema-invalid contract and a missing/unused credential before making any request. For
   local validation, define the server lifecycle in the implementation contract: start the
   target service with explicit safe test configuration on a non-conflicting port, capture
   its process ID, wait with a bounded timeout for readiness, run the CLI, and stop that
   process in a `finally`/cleanup step. A missing prerequisite is a blocker and failing
   result, never a pass.
3. Report changed files, commands/results, the `context-setter-e2e` result or precise
   blocker, required configuration/secrets, compatibility notes, and remaining deployment
   prerequisites.
4. Include this exact final section:

## Zapp Configuration

Provide concrete values and steps:

**Endpoint(s):** For each URL, the Endpoint match URL/prefix, the context key(s) it
injects and their delivery mechanism (Bearer/header/query/`ctx`), and, when the
user-context synchronization scenario is in scope, that the Endpoint must carry the
`observe_storage` tag.

**Context Setter Plugin configuration:**

| URL type | Your deployed URL | Supports |
| --- | --- | --- |
| Remote URL | `<url>` | `storage_keys` |
| Runtime URL (if in scope) | `<url>` | `storage_keys` / `persistent_keys` |

Note that Remote URL is fetched once at app initialization and only supports
`storage_keys`; Runtime URL is fetched post-init (and, with `observe_storage`, re-fetched
whenever an observed context key changes, such as on login/logout).

For the user-context synchronization scenario, state which account-scoped namespaces
purge to `null` on logout and confirm the device check that verifies it. Finish with
rebuild/test steps and explicit missing-Endpoint, credential, or safe-test-data blockers.
