Skip to content

app-showcase boots with three declared-but-inert wirings: a job with no handler, a capability that never materializes, and a retired retry alias #4888

Description

@xuyushun441-sys

Context

examples/app-showcase is the reference app — the thing the coverage test keeps
honest and the thing people copy. Three of its declarations are accepted at
authoring time and then quietly do nothing at runtime, each announced by a boot
warning. All three are the "declared, not enforced" shape the repo treats as a
bug class (ADR-0049), so they read as noise but are really dead wiring.

1. Scheduled job whose handler doesn't exist

WARN [AppPlugin] job handler not found in bundle.functions — skipping
{"appId":"com.example.showcase","job":"showcase_health_sweep","handler":"sweepProjectHealth"}

src/automation/jobs/index.ts:11 declares handler: 'sweepProjectHealth', and
that is the only occurrence of the string in the whole example — no function
of that name is exported into the bundle. So showcase_health_sweep is
registered and never runs.

The showcase is where "scheduled job" is supposed to be demonstrated end-to-end,
so this is a coverage hole as much as a warning: the capability appears exercised
while nothing executes.

2. Capability declared, referenced by a permission set, never materialized

WARN [security] capability has no owning package — not materialized {"name":"showcase.export_data"}

src/security/capabilities.ts:32 declares showcase.export_data, and
src/security/permission-sets.ts:190 puts it in OpsPermissionSet.systemPermissions
alongside the real setup.access.

Because it never materializes, that permission-set entry grants nothing — a
security declaration that reads as enforcement and isn't. Whatever the fix is
(give it an owning package, or drop it and the reference together), it should not
stay in the reference app in a state where copying it produces an inert grant.

3. Retired retry alias in the flow definitions

defineStack: flows[24].nodes[1].config.retry.backoffMs: 'retryDelayMs' → 'backoffMs'
(converted at load; conversion 'retry-policy-converged', retires in protocol 18).
Update the source to the canonical shape — the conversion stops running then.

Two sites still use the old spelling:

  • src/automation/flows/index.ts:984{ maxRetries: 3, retryDelayMs: 1000, backoffMultiplier: 2, maxRetryDelayMs: 10000 }
  • src/automation/flows/index.ts:1176{ maxRetries: 2, retryDelayMs: 500, backoffMultiplier: 2 }

The conversion carries an explicit retirement deadline (protocol 18), and the
example is the worst place to keep a shape that is about to stop working. This
one is a mechanical rename.

Why file these together

They share a root posture rather than a root cause: each is a declaration the
example makes that the runtime cannot honour, and each is currently "documented"
only by a line in the boot warning block. Happy to split if that suits triage
better.

Found while browser-sweeping showcase + Studio for #4879 (boot warnings on
main @ 0e96e46).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions