What types are valid in a constrain by clause?

← Web Services · Ref: Q1294

A 'constrain by' clause must reference functions that extend SecurityGate, CORSPolicy, or both. The compiler emits E12062 if the referenced type does not extend either.

VALID CONSTRAINT TYPES

SecurityGate: authenticates HTTP requests.

  MyGate is SecurityGate
    -> context as HTTPContext
    <- rtn as HTTPContext: context

CORSPolicy: validates cross-origin requests.

  MyCors is CORSPolicy
    -> origin as String
    <- rtn as Boolean: true

INVALID CONSTRAINT TYPES (E12062)

A regular function or class that does not extend either base:

  defines function
    NotAGate()
      <- rtn as String: "hello"
  defines service
    MyApi :/api constrain by NotAGate  <!- E12062 -!>

WHY THIS RESTRICTION

The router needs to know what to do with the constraint at runtime. SecurityGate functions receive HTTPContext and return an enriched context (or unset for rejection). CORSPolicy functions receive an origin String and return Boolean. Arbitrary functions have unknown signatures.

SINGLE VS DUAL CONSTRAINTS

One constraint: 'constrain by MyGate' (SecurityGate only)
Two constraints: 'constrain by MyGate and MyCors' (one SecurityGate + one CORSPolicy)

See Q1292 for security posture overview. See Q1293 for constraint resolution. See Q1295 for duplicate constraint roles.

Example

defines module qa.webdeep.constraintvalidation

  defines constant

    jsonType <- "application/json"
    noCache <- "no-cache"
    langEn <- "en"
    okStatus <- 200

  defines function

    <?-
      Valid SecurityGate: receives HTTPContext, returns HTTPContext.
    -?>
    TokenGate is SecurityGate
      -> context as HTTPContext
      <- rtn as HTTPContext: context

    <?-
      Valid CORSPolicy: receives origin String, returns Boolean.
    -?>
    OriginPolicy is CORSPolicy
      -> origin as String
      <- rtn as Boolean: true

  defines service

    <?-
      Service using a valid SecurityGate constraint.
    -?>
    GatedService :/api/gated constrain by TokenGate

      items() as GET for :/items
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as String: `{"items": ["a", "b"]}`
          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 ?

    <?-
      Service using both SecurityGate and CORSPolicy.
    -?>
    GatedWithCors :/api/cors constrain by TokenGate and OriginPolicy

      items() as GET for :/items
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as String: `{"items": ["c", "d"]}`
          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

    ConstraintValidationApp
      register GatedService()
      register GatedWithCors()

  defines program

    ConstraintTypeValidationDemo()
      stdout <- Stdout()
      stdout.println("Constraint type validation:")
      stdout.println("  TokenGate is SecurityGate -> valid")
      stdout.println("  OriginPolicy is CORSPolicy -> valid")
      stdout.println("  Regular functions -> E12062")

Common mistakes

E12062 — A 'constrain by' reference must extend SecurityGate or CORSPolicy; a plain function does not qualify. See ek9 -h E12062 for details.

Incorrect:

TokenGate()
      -> context as HTTPContext

Correct:

TokenGate is SecurityGate
      -> context as HTTPContext
Other ways to ask this
  • What is E12062 constraint type invalid?
  • Why must constrain by reference SecurityGate or CORSPolicy?
  • Can I use any function in a constrain by clause?
  • What types does the compiler accept for security constraints?

Coming from another language?

Java: Spring Security filters can be any class implementing OncePerRequestFilter — no compile-time type check. Python: Flask decorators are unchecked functions. Go: middleware is any http.Handler wrapper. Rust: Actix middleware must implement Transform trait. EK9: constraints must extend SecurityGate or CORSPolicy, verified at compile time.

Keywords: E12062, CORSPolicy, function, constrain, service, type, http, validation, SecurityGate