Why does constrain by X and Y fail when both extend SecurityGate?
← Web Services · Ref: Q1295
When 'constrain by X and Y' names two functions that both extend the same base (both SecurityGate or both CORSPolicy), the compiler emits E12064.
WHAT CAUSES E12064
Duplicate roles in a two-reference constraint:
constrain by GateAlpha and GateBeta
If both GateAlpha and GateBeta extend SecurityGate, the roles are duplicated.
WHY ONE OF EACH
The runtime applies the two constraints differently:
SecurityGate: called with HTTPContext, authenticates the request CORSPolicy: called with origin String, validates cross-origin access
Two gates or two policies create ambiguity — which one runs first? What happens if they disagree?
CORRECT PATTERN
One SecurityGate + one CORSPolicy:
constrain by JwtGate and AllowedOrigins
The router knows exactly which function handles authentication and which handles CORS.
SINGLE CONSTRAINT IS FINE
If you only need authentication without CORS, write 'constrain by JwtGate'. Or only CORS without authentication (unusual), write 'constrain by MyCors'.
See Q1292 for security posture overview. See Q1293 for constraint resolution. See Q1294 for constraint type validation.
Example
defines module qa.webdeep.duplicaterole defines constant jsonType <- "application/json" noCache <- "no-cache" langEn <- "en" okStatus <- 200 defines function <?- SecurityGate for JWT token validation. -?> JwtGate is SecurityGate -> context as HTTPContext <- rtn as HTTPContext: context <?- CORSPolicy that allows known origins. -?> KnownOrigins is CORSPolicy -> origin as String <- rtn as Boolean: true defines service <?- Correct: one SecurityGate + one CORSPolicy. The router knows which function handles which concern. -?> ValidDualConstraint :/api/dual constrain by JwtGate and KnownOrigins resource() as GET for :/resource <- response as HTTPResponse: () with trait HTTPResponse override content() <- rtn as Bytes: Bytes().withUtf8(`{"dual": "gate+cors"}`) override status() as pure <- rtn as Integer: okStatus override contentType() as pure <- rtn as String: jsonType override cacheControl() as pure <- rtn as String: noCache override contentLanguage() as pure <- rtn as String: langEn default operator ? defines application DuplicateRoleApp register ValidDualConstraint() defines program DuplicateConstraintRoleDemo() stdout <- Stdout() stdout.println("Duplicate constraint role rules:") stdout.println(" 'constrain by Gate and Cors' -> valid (different roles)") stdout.println(" 'constrain by Gate1 and Gate2' -> E12064 (both SecurityGate)") stdout.println(" 'constrain by Cors1 and Cors2' -> E12064 (both CORSPolicy)")
Other ways to ask this
- What is E12064 duplicate constraint role?
- Can I use two SecurityGate functions in constrain by?
- Why must the two constraint references have different roles?
- How do I combine SecurityGate and CORSPolicy in one clause?
Coming from another language?
Java: Spring Security allows chaining multiple filters of the same type — order is explicit in filter chain. Python: multiple decorators stack. Go: middleware wraps in order. Rust: Actix Transform chain. EK9: at most one SecurityGate and one CORSPolicy per constraint clause, enforced at compile time. No ambiguous filter ordering.
Keywords: CORSPolicy, service, role, constrain, E12064, http, SecurityGate, duplicate