feat(interceptors): ordered before-chains + cycle guard + ctx plumbing (§9.4 M1+M2)
M1: introduces a clone-cheap InterceptorCtx { interceptors, self_engine,
limits } threaded into every SDK register fn (kv/docs/files/queue/pubsub/http)
so the non-KV services carry the hook seam (unused until M7-M11); KvHandle
collapses its three fields into one ictx.
M2: replaces the nearest-only resolver with ordered before/after chains. The
trait becomes resolve(cx, service, op) -> InterceptorChain { before, after }
(migration 0074 adds a phase column + phase-aware unique indexes). The before
-chain runs ancestor->app (depth DESC) so a group compliance guard can't be
bypassed by a descendant; single-marker behavior is byte-identical to before.
An identity cycle guard (thread-local visited-set keyed by script_id) denies a
detected cycle, alongside the existing binary re-entrancy break. Fail-closed
verdict preserved (allow only on #{ allowed: true }; a Dangling entry or a
missing engine back-ref denies); app_id still derives from cx.app_id only.
after-chains resolve but stay unused until M3. Pinned by two new interceptor
journeys (ancestor->app chain ordering; self-referential no-recurse).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -60,13 +60,21 @@ pub fn register_all(
|
||||
limits: Limits,
|
||||
self_engine: Option<Arc<Engine>>,
|
||||
) {
|
||||
kv::register(engine, services, cx.clone(), limits, self_engine.clone());
|
||||
docs::register(engine, services, cx.clone());
|
||||
// §9.4 M1: build the interceptor ctx once and thread it into every SDK
|
||||
// service that has (or will gain) a before/after hook. Only `kv` runs a
|
||||
// hook today; docs/files/queue/pubsub/http carry it for M7–M11.
|
||||
let ictx = interceptor::InterceptorCtx {
|
||||
interceptors: services.interceptors.clone(),
|
||||
self_engine: self_engine.clone(),
|
||||
limits,
|
||||
};
|
||||
kv::register(engine, services, cx.clone(), ictx.clone());
|
||||
docs::register(engine, services, cx.clone(), ictx.clone());
|
||||
dead_letters::register(engine, services, cx.clone());
|
||||
http::register(engine, services, cx.clone());
|
||||
files::register(engine, services, cx.clone());
|
||||
pubsub::register(engine, services, cx.clone());
|
||||
queue::register(engine, services, cx.clone());
|
||||
http::register(engine, services, cx.clone(), ictx.clone());
|
||||
files::register(engine, services, cx.clone(), ictx.clone());
|
||||
pubsub::register(engine, services, cx.clone(), ictx.clone());
|
||||
queue::register(engine, services, cx.clone(), ictx);
|
||||
retry::register(engine, services, cx.clone());
|
||||
secrets::register(engine, services, cx.clone());
|
||||
vars::register(engine, services, cx.clone());
|
||||
|
||||
Reference in New Issue
Block a user