JSON Schema for CoSec Policies: Structure, Validation, and Examples

CoSec policies are governed by a strict JSON Schema defined in schema/cosec-policy.schema.json that specifies required metadata fields, conditional logic, and action matchers, and can be validated using any Draft-07 compliant validator.

The ahoo-wang/cosec repository implements a composable security framework where access control policies are defined as JSON documents. These documents must conform to a formal schema located in the repository's schema/ directory, ensuring type safety and structural consistency across global, system, and custom policy scopes.

Core Schema Structure

The root policy object requires specific metadata fields and contains the core authorization logic. According to schema/cosec-policy.schema.json, every policy must include category, name, description, tenantId, and type fields, alongside the operational components condition and statements.

The schema declares the JSON-Schema Draft-07 specification ("$schema": "http://json-schema.org/draft-07/schema#"), ensuring compatibility with standard validation libraries and IDE autocomplete features.

Policy Metadata Fields

The metadata section identifies the policy and its scope:

  • id: Optional unique identifier
  • category: Logical grouping (e.g., "security", "example")
  • name: Human-readable identifier
  • description: Detailed explanation of policy intent
  • tenantId: Isolation boundary (e.g., "default", "platform")
  • type: Policy scope classification

Policy Types

The type field accepts one of three enumerated values defined in #/definitions/policyType:

  • global: Applies across all tenants and systems
  • system: Bound to specific system contexts
  • custom: User-defined policies with limited scope

Conditions and Statements

CoSec policies implement a two-tier conditional logic structure. The top-level condition acts as a gatekeeper, while individual statements contain granular authorization rules.

Top-Level Conditions

The optional condition field in the policy root must evaluate to true for the policy to be considered. This field references schema/condition.schema.json via $ref, allowing complex boolean logic, authentication checks, or rate limiting to be evaluated before any statements are processed.

If the top-level condition fails, the entire policy is bypassed regardless of statement contents.

Statement Structure

The statements array contains the actual authorization decisions. Each statement object, defined in #/definitions/statement, requires:

  • action: Required matcher defining which requests apply (references schema/action.schema.json)
  • effect: Either allow or deny (defaults to allow per #/definitions/effect)
  • condition: Optional statement-level condition for fine-grained control
  • name: Optional identifier for the statement

Only the action field is mandatory within a statement.

External Schema References

The schema architecture promotes reusability through external references. Rather than embedding all definitions in the main file, CoSec modularizes complex validators into separate schema files.

Condition Schema

Located at schema/condition.schema.json, this file defines all available condition matchers including authenticated, groupedRateLimiter, path-based checks, and boolean composites. Policies reference these definitions via JSON Schema $ref pointers.

Action Schema

The schema/action.schema.json file specifies how to match HTTP requests. Actions can be:

  • Simple strings (exact match)
  • Arrays of strings (multiple exact matches)
  • Complex objects with path, method, or composite matching rules
  • Path-based patterns supporting wildcards (e.g., /api/**)

Shared Definitions

Common enumerations like effect (allow/deny) and pathOptions reside in schema/definitions.schema.json, preventing duplication across condition and action schemas.

Runtime Validation

The cosec-core/src/main/kotlin/me/ahoo/cosec/policy/PolicyLoader.kt class loads and validates JSON policies against these schemas at runtime. This ensures that only structurally valid policies are activated within the security framework, catching configuration errors during deployment rather than during request processing.

Practical Examples

Minimal Valid Policy

The following policy permits all HTTP GET requests globally:

{
  "category": "example",
  "name": "AllowAllGet",
  "description": "Allows all GET requests for any tenant",
  "tenantId": "default",
  "type": "global",
  "statements": [
    {
      "action": {
        "all": {
          "method": "GET"
        }
      }
    }
  ]
}

This example omits the top-level condition, meaning the policy is always evaluated. The statement defaults to effect: allow and matches any request using the GET method.

Complex Policy with Rate Limiting

This custom policy restricts POST requests to /api/** paths with per-user rate limiting:

{
  "category": "security",
  "name": "RateLimitedPost",
  "description": "Rate-limit POST requests to 10 per second per user",
  "tenantId": "platform",
  "type": "custom",
  "condition": {
    "authenticated": {}
  },
  "statements": [
    {
      "effect": "allow",
      "action": {
        "path": {
          "pattern": "/api/**",
          "method": ["POST"]
        }
      },
      "condition": {
        "groupedRateLimiter": {
          "part": "context.principal.id",
          "permitsPerSecond": 10,
          "expireAfterAccessSecond": 60
        }
      }
    }
  ]
}

Here, the top-level authenticated condition ensures only logged-in users trigger this policy. The statement matches POST methods on /api/** paths and applies a grouped rate limiter keyed by user ID.

Summary

  • CoSec policies conform to JSON-Schema Draft-07 defined in schema/cosec-policy.schema.json
  • The schema mandates metadata fields (category, name, tenantId, type) and authorization logic (statements)
  • Top-level conditions act as policy gates, while statement-level conditions provide granular control
  • Action matchers and condition validators are modularized into action.schema.json and condition.schema.json
  • Runtime validation occurs via PolicyLoader.kt, ensuring schema compliance before policy activation

Frequently Asked Questions

What JSON Schema version does CoSec use?

CoSec policies use JSON-Schema Draft-07, as declared in the $schema field of cosec-policy.schema.json. This version ensures broad compatibility with validation tools and libraries while supporting advanced features like $ref references for modular schema design.

Where are the condition and action schemas defined?

Condition matchers are defined in schema/condition.schema.json and action matchers in schema/action.schema.json. The main policy schema references these via $ref pointers, allowing the condition and action logic to be maintained independently while being reused across policy and statement definitions.

Can a policy have multiple statements with different effects?

Yes. A policy's statements array can contain multiple entries, each with independent effect values (allow or deny). CoSec evaluates statements sequentially, and the first matching statement determines the authorization result. This allows creating exceptions to broad allow rules by placing deny statements earlier in the array.

What happens if the top-level condition evaluates to false?

If the policy's top-level condition evaluates to false, the entire policy is bypassed and none of its statements are evaluated. This serves as an efficient gatekeeping mechanism—policies with unsatisfied top-level conditions consume no evaluation resources during request processing.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →