Keysmith
1.x
Docs/Keysmith/Policies
Open

Reading2 min
Updated31 Jul 2026
Sourcev1/subsystems/policies.mdx

The policy subsystem provides fine-grained control over API key behavior. Attach a policy to a key to enforce rate limits, restrict IP addresses, limit origins, and set maximum key lifetimes.

Creating a policy01

pol, err := eng.CreatePolicy(ctx, &policy.Policy{
    Name:           "Standard API",
    RateLimit:      1000,
    RateWindow:     time.Minute,
    AllowedIPs:     []string{"10.0.0.0/8", "172.16.0.0/12"},
    AllowedOrigins: []string{"https://app.example.com"},
    AllowedScopes:  []string{"read:users", "write:users"},
    MaxKeyAge:      90 * 24 * time.Hour,
})

Policy fields02

FieldTypeDescription
NamestringHuman-readable policy name
RateLimitintMaximum requests per window (0 = unlimited)
RateWindowtime.DurationRate limit window duration
AllowedIPs[]stringCIDR-notation IP allowlist (empty = all allowed)
AllowedOrigins[]stringHTTP origin allowlist (empty = all allowed)
AllowedScopes[]stringScopes this policy permits
MaxKeyAgetime.DurationMaximum key lifetime (0 = no limit)

Attaching a policy to a key03

Attach a policy at key creation time:

result, err := eng.CreateKey(ctx, &keysmith.CreateKeyInput{
    Name:     "Rate-Limited Key",
    PolicyID: &policyID,
})

Policy enforcement during validation04

When a key with an attached policy is validated, the engine checks:

  1. Rate limit -- If RateLimit > 0 and a RateLimiter is configured, the engine checks whether the key has exceeded its rate limit.

  2. IP allowlist -- If AllowedIPs is non-empty, the request IP must match one of the CIDR ranges.

  3. Origin allowlist -- If AllowedOrigins is non-empty, the request origin must match.

  4. Key age -- If MaxKeyAge > 0, the key must not exceed the maximum age.

Policy violations return ErrPolicyViolation.

Updating and deleting policies05

// Update
pol.RateLimit = 2000
err := eng.UpdatePolicy(ctx, pol)

// Delete
err := eng.DeletePolicy(ctx, policyID)

Policy store interface06

type Store interface {
    Create(ctx context.Context, p *Policy) error
    GetByID(ctx context.Context, id id.PolicyID) (*Policy, error)
    List(ctx context.Context, filter *ListFilter) ([]*Policy, error)
    Update(ctx context.Context, p *Policy) error
    Delete(ctx context.Context, id id.PolicyID) error
}