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

> Discover the CoSec policies JSON schema defining metadata, conditional logic, and action matchers. Validate your policies using a Draft-07 compliant validator for robust security.

- Repository: [Ahoo Wang/cosec](https://github.com/ahoo-wang/cosec)
- Tags: api-reference
- Published: 2026-02-23

---

**CoSec policies are governed by a strict JSON Schema defined in [`schema/cosec-policy.schema.json`](https://github.com/ahoo-wang/cosec/blob/main/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`](https://github.com/ahoo-wang/cosec/blob/main/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`](https://github.com/ahoo-wang/cosec/blob/main/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`](https://github.com/ahoo-wang/cosec/blob/main/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`](https://github.com/ahoo-wang/cosec/blob/main/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`](https://github.com/ahoo-wang/cosec/blob/main/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`](https://github.com/ahoo-wang/cosec/blob/main/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`](https://github.com/ahoo-wang/cosec/blob/main/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:

```json
{
  "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:

```json
{
  "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`](https://github.com/ahoo-wang/cosec/blob/main/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`](https://github.com/ahoo-wang/cosec/blob/main/action.schema.json) and [`condition.schema.json`](https://github.com/ahoo-wang/cosec/blob/main/condition.schema.json)
- Runtime validation occurs via [`PolicyLoader.kt`](https://github.com/ahoo-wang/cosec/blob/main/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`](https://github.com/ahoo-wang/cosec/blob/main/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`](https://github.com/ahoo-wang/cosec/blob/main/schema/condition.schema.json) and action matchers in [`schema/action.schema.json`](https://github.com/ahoo-wang/cosec/blob/main/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.