---
name: applicaster-parent-lock-pin
description: "Parent Lock PIN backend: use when implementing or hardening a customer-hosted CloudEvents endpoint for Quick Brick Parent Lock remote PIN flows — verify (com.applicaster.pin.v1), set (pin.set.v1), change (pin.change.v1, two steps), or PIN recovery (pin.recovery.requested.v1). Works in any stack; validates request AND response boundaries; ships a skill-local pin-e2e tool that black-box tests a running endpoint."
---

# applicaster-parent-lock-pin

Implement or harden the **Parent Lock PIN backend** — the customer-hosted CloudEvents endpoint the Quick Brick Parent Lock plugin (`parent-lock-qb`) calls for remote PIN verify, set, change, and recovery. The deliverable is an endpoint that satisfies the documented contract, with validation on **both** the request boundary and the response boundary, plus an executable proof via the skill-local [PIN E2E tool](tools/pin-e2e/README.md).

For general Cloud Events receiver work (multi-event dispatch, allowlists, idempotency across the full protocol), use [applicaster-cloud-events](../applicaster-cloud-events/SKILL.md). This skill covers the **PIN lifecycle boundary** only.

For Zapp Studio setup, client flows, and the `pinCode` feed action, the live [Parent Lock guide](https://docs.applicaster.com/using-zapp/auth/parent-lock) is the product reference. The live [PIN Code integration guide](https://docs.applicaster.com/integrations/pin-code) is the wire-contract authority.

## Scope

- Use when building or hardening an endpoint that handles one or more of:
  - `com.applicaster.pin.v1` — validate a PIN (Remote Verify)
  - `com.applicaster.pin.set.v1` — set a new PIN
  - `com.applicaster.pin.change.v1` — change PIN (`step: verify_current` then `confirm_change`)
  - `com.applicaster.pin.recovery.requested.v1` — trigger a PIN reset email
- **Adapt to the target project's stack** — language, framework, validation library, HTTP client, test runner, config/secrets, and deployment conventions. Do not assume a JavaScript implementation.
- `com.applicaster.pin.reset.v1` is **not implemented** in the current Parent Lock client. Do not build for it unless the developer explicitly requests forward compatibility.
- Math Challenge (local-only, no network) is out of scope — it requires no backend.
- The contract is fixed and documented. Confirm live docs; do not invent event types, `data` fields, or status codes.

## Non-Negotiable Gates

1. Every PIN event validates its **request** envelope and event-specific `data` fields before doing any work, and validates its **response** payload before returning it. See [validation-patterns.md](references/validation-patterns.md).
2. Return HTTP `200` or `201` on success and HTTP `400` for invalid PIN or validation failures. Prefer `{ "message": "..." }` in error bodies — the app surfaces `error.response.data.message`.
3. Never log raw PIN values, tokens, or user identifiers. Logs carry only operation, event type, event ID, and status class.
4. Do not report the work complete without a `## Zapp Configuration` section that walks the customer through Parent Lock plugin setup per the live Parent Lock guide.
5. Do not claim end-to-end validation without running the `pin-e2e` tool against a running server, or naming that as the blocker.

## 1. Establish facts

1. Fetch the current [PIN Code](https://docs.applicaster.com/integrations/pin-code), [Parent Lock](https://docs.applicaster.com/using-zapp/auth/parent-lock), and [Cloud Events PIN sections](https://docs.applicaster.com/integrations/cloud-events) documentation. Read [pin-contract.md](references/pin-contract.md) alongside and reconcile drift toward live docs.
2. Inspect the target project and determine, without asking: stack, existing Cloud Events or PIN routes, validation approach, test/build commands, deployment URL shape, and identity/account model for PIN storage. Only ask for details the project cannot answer yet.
3. Read [validation-patterns.md](references/validation-patterns.md), [decision-guidance.md](references/decision-guidance.md), and [acceptance-matrix.md](references/acceptance-matrix.md).

Completion: the target stack, events in scope, and validation/test conventions are evidenced by code and live docs.

## 2. Resolve developer decisions

Present a concise, sourced fact summary, then ask only what facts cannot settle. Ask one question at a time with the discovered constraint, a recommended answer, and the consequence of choosing otherwise. Use [decision-guidance.md](references/decision-guidance.md) for branching.

Resolve when facts leave real ambiguity:

1. Which events are in scope for this piece of work (verify only vs full lifecycle including set/change/recovery).
2. How PINs are stored and keyed (per account, per device, per profile) and whether kids profiles must be rejected server-side as well as client-side.
3. PIN format rules (length, allowed characters) and whether they match the Zapp manifest **PIN Length** setting.
4. Whether verify success should return the documented `"Valid Pin Code"` subject and `id: <submitted-pin-value>`, or a custom subject (both are accepted by the client when HTTP status is 200/201).
5. For change PIN: whether `verify_current` and `confirm_change` are separate handler paths or a single dispatcher keyed on `data.step`.
6. For recovery: how the reset email is triggered and what identity source ties the request to an account.

If live documentation cannot be fetched, state that the bundled snapshot may be stale and ask whether to proceed from [pin-contract.md](references/pin-contract.md).

Completion: every applicable decision has a recorded developer answer.

## 3. Confirm before edits

Present a concise contract containing:

- Event types in scope and their `data` field requirements.
- Success and error responses per event (status code, body shape, receipt `subject`/`id` where documented).
- PIN storage model, validation rules, and kids-profile policy.
- Affected routes/files, tests to add or update, and configuration/secrets required.

Wait for explicit approval.

Completion: the developer has approved every non-discoverable choice.

## 4. Implement the contract

1. Validate CloudEvents envelope shape and event-specific `data` before any store or provider work.
2. Implement each event's documented success and error responses. Do not force one shared body across all PIN events.
3. Ensure no route logs raw PIN values or identifiers.
4. Make only the direct fixes needed for the approved contract.

Completion: code matches the approved contract.

## 5. Verify and hand off

1. Run the target project's unit/integration tests for the PIN routes.
2. Run the skill-local `pin-e2e` tool against a running server with disposable test PIN values:

   ```sh
   node <skill-tools-dir>/pin-e2e/cli.js \
     --endpoint-url https://api.example.com/cloud-events \
     --valid-pin 1234 \
     --invalid-pin 0000 \
     --new-pin 5678
   ```

3. Report any failures with sanitized evidence (no PIN values in output).
4. Produce the Zapp Configuration handoff below.

Completion: tests and e2e pass, or blockers are named.

## Zapp Configuration

Fetch the current Parent Lock guide before producing this section. Include:

1. Add the Parent Lock plugin (`parent-lock-qb`) and Parent Lock screen to the app layout.
2. Enable **Remote PIN Verification** and configure the **PIN Verification Endpoint** data source to `<DEPLOYED_PIN_ENDPOINT_URL>`.
3. Set **PIN Length** to match the server validation rule.
4. For feed-driven flows, wire `pinCode` actions with the correct `options.flow` and `typeMapping` per [PIN Code — pinCode action](https://docs.applicaster.com/integrations/pin-code#pincode-feed-action).
5. For content gates, attach the Parent Lock preload hook per the Parent Lock hook behavior section.
6. Ordered validation: verify a known-good PIN, verify a known-bad PIN returns 400, exercise set/change if in scope, exercise recovery if in scope.
7. `Documentation checked: YYYY-MM-DD` with links to the guides used.
