Skip to content

feat(server): composeMethod — typed before/after hooks with {shortCircuit: T} discriminated wrapper #454

@bokelley

Description

@bokelley

Parent: #452

JS source

.changeset/compose-method-helper.md (6.7).

Pattern

Wrap individual DecisioningPlatform methods with hooks:

  • before(params) -> ShortCircuit | None. Return None to fall through to inner method, or {"short_circuit": value} to skip the inner method and use value as the result.
  • after(result, params, ctx) -> result runs on the result whether it came from the inner method OR a before short-circuit.
  • Critically: after runs BEFORE response-schema validation, so adopters can tweak shape before the framework validates.

Proposed API

from adcp.decisioning import compose_method, require_account_match, require_advertiser_match, require_org_scope

platform.create_media_buy = compose_method(
    inner=platform.create_media_buy,
    before=require_account_match,           # raises PERMISSION_DENIED if mismatch
    after=lambda result, params, ctx: ...,  # echo back custom fields
)

Security composers (each is a valid before hook):

  • require_account_match — fails if params.account_id doesn't match resolved auth principal's account.
  • require_advertiser_match — fails if params.advertiser_id not in resolved principal's advertisers.
  • require_org_scope — fails if resolved principal isn't operator-scoped.

All raise typed PermissionDeniedError (#3).

Acceptance criteria

  • compose_method helper exported from adcp.decisioning.
  • 3 security composers exported.
  • Tests cover: before-only, after-only, both, short-circuit path, exception in before propagates, after runs on short-circuited result.

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