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:
constrain by JwtGate
Or only CORS without authentication (unusual):
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 String: `{"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: constrain, role, service, CORSPolicy, duplicate, SecurityGate, http, E12064