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.
Parent: #452
JS source
.changeset/compose-method-helper.md(6.7).Pattern
Wrap individual
DecisioningPlatformmethods with hooks:before(params) -> ShortCircuit | None. ReturnNoneto fall through to inner method, or{"short_circuit": value}to skip the inner method and usevalueas the result.after(result, params, ctx) -> resultruns on the result whether it came from the inner method OR abeforeshort-circuit.afterruns BEFORE response-schema validation, so adopters can tweak shape before the framework validates.Proposed API
Security composers (each is a valid
beforehook):require_account_match— fails ifparams.account_iddoesn't match resolved auth principal's account.require_advertiser_match— fails ifparams.advertiser_idnot in resolved principal's advertisers.require_org_scope— fails if resolved principal isn't operator-scoped.All raise typed
PermissionDeniedError(#3).Acceptance criteria
compose_methodhelper exported fromadcp.decisioning.