---
name: applicaster-dsp-content-feeds
description: "Implement or harden a customer-hosted Applicaster Pipes2 JSON content-feed service. Use for static collection feeds and, when explicitly selected, entry-driven dynamic feeds, search, and protected playback/Fetch Entry. Works in any stack, preserves existing DSP behavior, validates Pipes2 responses at the service boundary, and includes a black-box validator for a running service."
---

# applicaster-dsp-content-feeds

Implement or harden a customer-hosted **Pipes2 JSON feed service**. A static collection
feed is always in scope. Entry-driven dynamic feeds, search, and protected playback are
optional scenarios that must be explicitly selected; a selected scenario cannot be silently
skipped. The deliverable validates inputs and every Pipes2 response at the service boundary,
then proves running behavior with [dsp-feed-validator](tools/dsp-feed-validator/README.md).

## Scope and non-negotiable gates

1. Adapt to the target codebase's language, framework, router, validation library, test and
   build commands, configuration/secrets, deployment, and logging conventions. Do not assume
   JavaScript or add dependencies without an existing-project need.
2. Before implementation, fetch the current live Pipes2 schema, endpoint, custom-DSP,
   search, Fetch Entry, Video Preload, Endpoint/context-key, Pipes2-feed, and dynamic-feed
   documentation. Reconcile it with [the local references](references/pipes2-contract.md);
   live documentation is semantic authority. Also read
   [endpoints-manifest.md](references/endpoints-manifest.md) — every DSP must expose this
   route.
3. Validate request inputs before use and each Pipes2 response before returning it through the
   target project's existing validation convention. Enforce the permissive versioned `v1`
   profile plus selected-scenario assertions. Log violations without secrets and return a safe
   `5xx`, never malformed output. The bundled CLI independently tests a running service; it is
   not an application dependency or a substitute for response-boundary validation.
4. Successful feeds use `application/vnd+applicaster.pipes2+json` (parameters allowed), a
   non-empty feed `id`, `type.value: "feed"`, and an `entry` array with non-empty entry ids and
   types. Keep documented extensions open; validate video content and link entries when present
   and absolute pagination `next` URLs.
   For every route, explicitly decide each documented optional field as required by its returned
   entry types and configured Zapp mapping, deliberately omitted, or not applicable. Visual
   collection entries normally need a title and the image keys their cell styles consume, but do
   not make either universal without evidence from the target configuration.
5. Preserve an existing DSP's public routes, payloads, consumers, and tests. Make only additive
   or explicitly approved breaking changes, and identify every behavior change before editing.
6. Do not claim end-to-end validation without a successful selected-scenario
   `dsp-feed-validator` run, or a concrete blocker for a missing runnable URL, credential,
   expected entry id, query, or safe test data.
7. Do not finish without a `## Zapp Studio Configuration` handoff. Create a persistent target
   repository report only when that project already has a suitable convention or the developer
   asks for one.

## Error and context-key contract

Before edits, define every route's accepted inputs, including each required `ctx` key, expected
type/format, and the safe error response for each invalid case. Never invent a context key or
assume a missing value has a safe default; consult [available-context-keys.md](references/available-context-keys.md)
and ask the developer when the project, Zapp configuration, and that reference do not establish it.

1. For a route that requires `ctx`, a missing `ctx`, invalid base64url, invalid JSON, missing
   required key, or invalid key value returns a sanitized `400`. Do not decode or log values until
   after validation; never return the missing key name when it could expose authorization design.
2. A selected dynamic route or `/search` with a missing, blank, malformed, or invalid resolved
   input returns a sanitized `400` before routing or querying. Do not substitute a catalogue-wide
   query, a default entry, or an unvalidated placeholder value.
3. Fetch Entry without valid playback credentials, or with credentials that fail authentication or
   authorization, returns the required sanitized `403`. Keep an authentication-required origin
   feed a successful `200` metadata feed as described in the selected protected-playback contract.
4. Missing required server configuration should prevent the affected service from starting when
   that matches project convention; otherwise fail requests safely without exposing configuration
   names or values. Upstream/source failures, response-rendering failures, and response-validation
   failures log sanitized diagnostics and return a safe `5xx`; never return malformed Pipes2 JSON.
5. Use the target project's established error body and status conventions. If none exists, agree
   one before implementation, cover every case above in endpoint tests, and document it in the
   implementation contract. Do not disclose tokens, `ctx`, credentials, internal URLs, stack
   traces, or upstream response bodies in client errors or logs.

## 1. Establish facts

1. Fetch and reconcile the live documentation required by Gate 2. Read
   [pipes2-contract.md](references/pipes2-contract.md),
   [context-and-dynamic-url-rules.md](references/context-and-dynamic-url-rules.md),
   [validation-patterns.md](references/validation-patterns.md),
   [available-context-keys.md](references/available-context-keys.md), and
   [endpoints-manifest.md](references/endpoints-manifest.md).
2. Inspect the target project before asking questions. Record the stack; routes and callers;
   catalogue/source and entry identifiers; Pipes2 payloads; validation and test conventions;
   authentication/context-key use; config/secrets; deployment URL shape; and existing Zapp
   configuration/docs. For a greenfield project with no discernible stack, ask the developer to
   select one and default configuration/secrets to environment variables.
3. For an existing DSP, inventory existing routes, consumers, and tests. Treat changed public
   output, routing, authentication, caching, or Studio locators as compatibility impacts.

Completion: evidence the stack, existing behavior, source mappings, validation convention, 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, recommendation, and consequence. Resolve material unknowns
in dependency order:

1. Which optional scenarios apply: entry-driven dynamic, search, protected playback.
2. **Endpoints manifest** (required for every DSP): Identify the project's versioning convention
   (e.g. `/v1/`, `/v3/`) for the manifest route. Inventory which features are enabled (auth,
   geo-restriction, ad macros, language selector) to determine which `context_obj` keys must be
   dynamically appended per endpoint. Confirm whether multiple API versions require separate
   manifest exports (see [endpoints-manifest.md](references/endpoints-manifest.md)).
3. Catalogue/source and entry-id mapping; routes/locators; pagination; and type mappings.
   Inventory each mapped screen and cell style's displayed fields and image keys, then record a
   per-route presentation-field contract (for example `title` and `thumbnail-16x9`).
3. Dynamic placeholder names and their explicit referring-entry field bindings.
4. Search behavior. It is exactly `/search?q={{q}}`, consumes a non-empty `q`, and returns the
   base feed contract. `filterTag` is outside first-version scope.
5. Public versus protected feeds; required context keys, expected values, and narrowest HTTPS
   Endpoint prefix. Decode `ctx` as base64url JSON, apply the error and context-key contract,
   and never log it or contained credentials. Treat tokens in it as normal credentials.
6. Protected-playback authorization and playable-content source. Default to a Bearer
    `quick-brick-login-flow.access_token`; use `ctx` only when multiple context values are needed.
    The protected origin remains a successful `200` metadata feed: it signals authentication with
    `extensions.requires_authentication: true`, links to Fetch Entry, and omits direct `content`.
    Fetch Entry, not the origin feed, returns sanitized `403` when playback credentials are absent
    or unauthorized.
7. The target project's response-validation convention and runnable validator URLs, credentials,
    expected ids, queries, and safe test data. For protected playback, the validator must prove
    that the origin entry and Fetch Entry result have matching `type.value` values.

## 3. Confirm before edits

Present an implementation contract and wait for explicit approval. Include selected scenarios;
each route/Feed Locator and input binding; source mapping; context/auth behavior; request,
response, error handling, and presentation-field contract; target-project validator; changed files; compatibility impact;
the exact `dsp-feed-validator` command and prerequisites; and Zapp Studio changes. Always include
the endpoints manifest route, its version prefix, and the full resolved `context_obj` per endpoint.
Refresh it if a material decision changes.

## 4. Implement the contract

1. Implement or verify the static collection route and selected scenarios using existing project
   patterns. Validate route/query/context values before use, apply the agreed error mapping, and
   test every invalid-input and missing-context-key case.
2. Implement the endpoints manifest route (see
   [endpoints-manifest.md](references/endpoints-manifest.md)):
   - Register `GET /<version>/endpoints-manifest` using the project's versioning convention.
   - Define a static base manifest with `{{host}}` URL templates for every route the DSP exposes.
   - At request time, resolve `{{host}}` to the real hostname from the incoming request URL.
   - Dynamically append `context_obj` items for each enabled feature (auth tokens, geo token,
     ad macros, language) rather than hard-coding optional keys in the static definition.
   - If the service has multiple API versions, export and register a separate manifest per version.
   - Return the resolved manifest as `application/json`; validate its shape before returning.
3. Render each feed success response, validate it with the target validator and the `v1` profile,
   then set the Pipes2 media type and return it. On validation failure log only sanitized
   diagnostics and send a safe `5xx`.
   Enforce the route's approved presentation-field contract in addition to the base profile.
4. Use whitespace-free `{{name}}` Feed Locator placeholders and bind each explicitly to a
   referring-entry field. Validate resolved dynamic values before routing or querying.
5. For protected playback, origin entries set `extensions.requires_authentication: true`, include
   `link.href`, and omit direct `content`. The one playable entry returned by Fetch Entry must
   have the same `type.value` as the protected origin entry that links to it. Fetch Entry
   authenticates and authorizes before returning it; unauthenticated access returns `403`.
6. Make only the necessary changes. Keep secrets in the target project's existing convention and
   never log tokens, `ctx`, or stream authorization details.

## 5. Verify and hand off

1. Run the target formatter, typecheck, and relevant endpoint tests.
2. Define a versioned `dsp-feed-validator` contract that declares every selected scenario,
    per-scenario expected entry id, authentication mode, required `ctx` keys, and exact sanitized
    error status/media type. Run the bundled CLI with `--contract`, required safe credentials, and
    a sanitized JSON report. It rejects missing or unused credentials before requests and probes
    missing/malformed `ctx` plus every declared missing-key case. For local validation, define the
    server lifecycle in the implementation contract: start
    the target service with explicit safe test configuration, including safe credentials for the
    selected authentication route when authentication is selected (a Bearer token for the Bearer
    route, or correctly encoded `ctx` for the context route), on a non-conflicting port; capture
    its process ID; wait with a bounded timeout for its static URL to return the expected `2xx`;
    run the CLI; and stop that specific process in a `finally`/cleanup step. Treat readiness
    timeout or an unexpected response as a blocker and report it before running the CLI.
    Report the URL, port, startup command, validator command, process cleanup result, and any
    already-running server conflict. A missing prerequisite is a blocker and failing result, never
    a pass.
3. Report changed files, commands/results, validator result or precise blocker, required
   configuration/secrets, compatibility notes, and remaining deployment prerequisites.
4. Include this exact final section:

## Zapp Studio Configuration

Provide concrete values and steps:

**Endpoints manifest:** Register `GET /<version>/endpoints-manifest` in Zapp Studio → Data
Sources → Endpoints. Zapp fetches this URL once and auto-populates all declared endpoints and
their context-key requirements. Manual endpoint entry is not needed for endpoints declared in
the manifest.

| Endpoint | HTTPS base URL | Context key | Delivery type | Reason/prerequisite |
| --- | --- | --- | --- | --- |
| `<name>` | `<url>` | `<key or none>` | `<Bearer/header/query/ctx>` | `<reason>` |

Use the narrowest Endpoint prefix. Warn that only the longest matching Endpoint supplies context
keys. Then provide a Pipes Feed table with name, Endpoint, Feed Locator, dynamic bindings, type
mapping, and a resolved URL example. Include selected static, dynamic, and search feeds.

For protected playback, state the origin behavior, Fetch Entry URL and credential transport,
then install **Video Preload** for every relevant version/platform, add **Preload Video Screen**,
configure Fetch Entry, and attach it as the player screen's **Preload Video** storyboard hook.
Finish with rebuild/test steps and explicit missing-plugin, token, endpoint, or safe-test-data
blockers.
