publ betaReference (MCP guide)
Open publ console

Manage installed features

# Manage installed features

Use the existing channel's feature store workflow for catalog inspection, confirmed zero-cost installation and explicit removal. Feature content/operation, visitor ACLs, default entry, channel creation and financial changes are separate tasks.

## Read, plan and verify

1. Use [get](../tools/publ_papps_get.md) to inspect the current plan, catalog, installed IDs, pricing, restrictions and revision. OWNER or a selected-channel DELEGATEE with `MANAGE_P_APP_INSTALL_UNINSTALL` is required for the store tools.
2. For installation, choose one returned code and pricing model whose prerequisites and explicit zero fees are confirmed. For removal, select the exact installed ID/code and explain the irreversible impact. Use [human handoff](../tools/publ_billing_handoff.md) for financial changes.
3. Submit a dry run with a stable request ID and the returned revision. Review the plan, then use the same business inputs with `dryRun:false` within the user's authorized task.
4. Interpret task phase, result code and verification together. Refresh current state through get after completion; a replayed result is historical.

Read a selected feature:

```json
{"channelCode":"selected-channel-code","pAppCode":"A00003"}
```

Plan installation using the returned pricing ID and full-snapshot revision:

```json
{"requestId":"feature-workflow-example-001","channelCode":"selected-channel-code","expectedRevision":"0000000000000000000000000000000000000000000000000000000000000000","pAppCode":"A00003","ppmid":"pricing-model-from-get","dryRun":true}
```

These values are placeholders, not evidence that a feature is available or free. [Install](../tools/publ_papp_install.md) and [remove](../tools/publ_papp_remove.md) document the full input contracts.

## Costs and prerequisites

Direct installation requires all three installation, monthly-base and pay-as-you-go prices to have the channel currency and an amount string matching the runtime regex `/^0+(?:\.0+)?$/`, such as `0`, `00` or `0.00`. KRW uses the local fee fields; USD uses the corresponding Global fields. Missing/null amounts, currency mismatch, negative/signed/exponent forms and nonzero values are not confirmed zero. No trimming, numeric coercion or FREE-label inference is used. Pricing must also match the selected code, `ppmid` and current plan's class prefix.

Catalog visibility and release are separate. Hidden or unreleased features, existing installations and missing prerequisite features block new installation. C00013/X00005 require a separate account allowlist check in the console. FREE_TRIAL blocks F00001 and 3RD_*; 3RD_A00001/3RD_A00002 also need BUSINESS account type, with null treated as unknown. Returned `installBlock` explains the current reason. Parents are never silently installed.

Removal blocks defaults and protected system/commerce/extension codes, unreleased entries and unresolved catalog policy. Existing extension or multi-instance children must be handled separately. The workflow never cascades a deletion. Current `removeBlock` and detail readback are authoritative for the observed target; a catalog search result alone is insufficient.

The catalog may contain explicit triple-null placeholders. The adapter omits them from selectable metadata and reports their codes, while still rejecting malformed present metadata and duplicate identifiers. `allRowsUsable:false` is a disclosure of omissions, not permission to guess eligibility or price. A null installed alias remains null.

## Recover the original task

```json
{"taskId":"feature-workflow-example-001","taskType":"papp-lifecycle"}
```

Use that input with [status](../tools/publ_task_status.md), then [resume](../tools/publ_task_resume.md) when continuing the same authorized operation is appropriate. Status reports saved phase, last result and pending refresh, checking connection identity; it does not read current business state or perform the remaining work.

| Phase or condition | Implemented behavior |
| --- | --- |
| Fresh dry run | Validate current revision/policy; no new job, install/delete or refresh |
| Existing matching dry run | Return saved phase/task identity; no fresh catalog/eligibility comparison |
| `prepared` | Recheck original snapshot, policy and removal detail where applicable; may send the original request |
| Definite install/delete rejection | Return the original job to prepared, retaining its original input; later continuation rechecks before another dispatch |
| `sent` with unknown outcome | Never resend installation/deletion. Resume may still perform a not-yet-sent refresh before verifying the installed list and detail |
| Sent refresh with unchanged credential version | Return `CHANNEL_REFRESH_OUTCOME_UNKNOWN`; trusted connection recovery is required before continuing |
| `verified` | Recheck the final installed state and its snapshot checkpoint before completion |
| `done` | Return the stored completion; get supplies a new observation |

This workflow's definite-rejection rule differs from the display writer's never-resend-after-dispatch policy. Same-ID apply must retain the original expected revision, code, pricing/installed ID and confirmation; changing them yields `TASK_CONTEXT_CHANGED`. Do not generate another request ID to bypass uncertainty. No automatic rollback, recovery of deleted feature data or atomic server compare-and-swap is provided.

Completion preserves unrelated installed entries and the original plan, currency and account type. Install requires exactly one new matching instance with the selected active current pricing and no scheduled next plan; removal requires exact target absence in list and detail. The final full snapshots must be stable. This is stored-state verification, not visitor use, feature-content validation or financial completion.

## Saved record identity

Stored task IDs must match the requested lookup key. An intact task copied under
a different key, or a present JSON null/false/zero/empty-string record, returns
`TASK_STATE_UNVERIFIED` before context/business calls. Preserve both the original
record and the requested file for inspection; do not replace or delete them to
bypass uncertainty. Only an actually absent file means no task.

An existing matching dry-run returns its saved plan with `historical:true`,
`replayed:true`, and `verification.currentStateVerified:false`. It does not recheck
current install/removal eligibility. Follow `nextStep` to `papps_get` for the exact
original channel and feature before planning further changes. The journal is
unchanged and no installation, removal or credential refresh is sent by this plan.

## Saved record consistency

Before using an existing task, the workflow checks its original input fingerprint,
before-state revision, allowed progress/refresh/checkpoint combinations and any
stored completion. A completed result must match the original channel, feature,
task, pricing/removed target and preserved installed rows. Inconsistency returns
`TASK_STATE_UNVERIFIED` before context/business calls and leaves the record intact.
Preserve it for inspection rather than repairing fields or starting replacement
work. This validates consistency, not cryptographic authenticity or current server
state. Historical completion still requires a fresh get for current values.

## Detail pricing evidence

An installed-list row may omit pricing or contain null while the detail response
confirms valid active pricing. Those list values remain unchanged. New tasks keep
a separate internal detail-verification receipt and require it for completed
installation recovery. The receipt binds the observed installed ID, feature code,
requested active price and absence of a scheduled next price. Legacy histories
without that receipt retain their existing verified-method metadata and target/
preservation checks; no receipt or list pricing is invented. Historical replay
is not a current detail read. Invalid detail identity/pricing cannot confirm a
new installation, and uncertain effects are never resent.

## Installed-feature availability

Installation enables the feature; there is no separate activation/deactivation
step. Raw `isActive` is a legacy observed value and must not be interpreted as an
activation prerequisite. Use `design_access_get` and `design_access_apply` for
supported visitor-access restrictions, and retain their paid-access limitations.
Uninstall destroys data and is not a substitute for restricting access. Catalog
publication, product availability, pricing and notification switches remain
separate settings.