Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Secret Policies

Endpoint reference for value-generation policies — recipes ScaiVault uses to mint new secret values during rotation, signup, or on-demand preview. (Not to be confused with access policies, which control who can read secrets.)

Base path: /v1/secret-policies/

Model#

A secret policy says: "when you need to generate a new value for this kind of secret, follow this recipe." Recipes have one or more fields; each field has a generator and parameters.

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "id": "sp_db_passwords",
  "name": "Database Passwords",
  "policy_type": "password",
  "fields": [
    {
      "name": "password",
      "generator": "random",
      "config": {
        "length": 32,
        "charset": "safe",
        "require_upper": true,
        "require_lower": true,
        "require_digit": true,
        "require_symbol": true
      }
    }
  ],
  "is_active": true,
  "description": "Strong 32-char passwords for database users",
  "created_at": "...",
  "updated_at": "..."
}

When a rotation policy with auto_generate: true fires for a secret, ScaiVault runs the linked secret-policy's recipe and writes the result as the new version. You can also generate previews for testing.

Policy types#

Type Typical fields Common use
password password Database users, service passwords
api_key api_key, optional api_secret API tokens
oauth_client client_id, client_secret OAuth credentials
ssh_key private_key, public_key SSH key pairs
custom Whatever you define Anything else

policy_type is a hint to the UI; it doesn't constrain fields. The combination of fields is what determines the generated shape.

Generators#

Each field declares a generator and a config:

Generator Config keys Output
random length, charset, require_* Random string from the charset
hex length Random lowercase hex of N chars
uuid version (4/7) UUIDv4 or UUIDv7
template template Substitutes {{random:N}}, {{uuid}}, {{hex:N}}, {{timestamp}} placeholders
rsa_keypair bits (2048/4096) PEM-encoded private + public
ec_keypair curve (P-256/P-384) PEM-encoded private + public
ssh_keypair key_type (ed25519/rsa), comment OpenSSH-formatted private + public
bcrypt_hash length, rounds Random password and its bcrypt hash
static value Literal value — useful for templates

Charsets#

Name Characters
alphanumeric a-zA-Z0-9
alpha a-zA-Z
numeric 0-9
hex 0-9a-f
safe Alphanumeric plus _-. — safe in URLs and shells
printable All printable ASCII except space
symbols `!@#$%^&*()_-+=[]{}
alphanumeric+symbols Alphanumeric plus the symbols set

require_upper, require_lower, require_digit, require_symbol boolean flags force at least one character from each class. Useful for satisfying password complexity requirements at downstream systems.

Endpoints#

GET /v1/secret-policies#

List policies in the current tenant.

Query: policy_type, active_only, limit, cursor.

Response:

json
1
2
3
4
5
6
7
{
  "data": [
    {"id": "sp_abc", "name": "...", "policy_type": "password", "is_active": true, "fields_count": 1}
  ],
  "cursor": null,
  "has_more": false
}

Scope: policies:read or admin.

POST /v1/secret-policies#

Create.

Body:

Field Required Description
name Yes Tenant-unique
policy_type Yes See type table
fields Yes Array of {name, generator, config}
description No

Scope: policies:write or admin.

GET /v1/secret-policies/{id}#

Returns the full policy.

PATCH /v1/secret-policies/{id}#

Partial update (any subset of name, description, fields, is_active).

DELETE /v1/secret-policies/{id}#

Returns 409 policy_in_use if any rotation policy or secret references it.

POST /v1/secret-policies/{id}/generate#

Generate a preview value without storing anything. Returns the generated fields. By default values are masked (••••••) — pass ?show=true to get plaintext (audit-logged).

Response:

json
1
2
3
4
5
6
7
{
  "policy_id": "sp_abc",
  "fields": {
    "password": "kX9#mP2$vL5@nQ8&wR3!T7^bY4*"
  },
  "generated_at": "..."
}

Scope: policies:read (mask) or policies:write (plaintext).

GET /v1/secret-policies/_types#

Catalog of available policy types, generators, and charsets — useful for building UIs.

Response:

json
1
2
3
4
5
{
  "types": ["password", "api_key", "oauth_client", "ssh_key", "custom"],
  "generators": ["random", "hex", "uuid", "template", "rsa_keypair", "ec_keypair", "ssh_keypair", "bcrypt_hash", "static"],
  "charsets": ["alphanumeric", "alpha", "numeric", "hex", "safe", "printable", "symbols", "alphanumeric+symbols"]
}

Examples#

Strong password (32 chars, all classes)#

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "name": "Strong Password",
  "policy_type": "password",
  "fields": [{
    "name": "password",
    "generator": "random",
    "config": {
      "length": 32,
      "charset": "alphanumeric+symbols",
      "require_upper": true,
      "require_lower": true,
      "require_digit": true,
      "require_symbol": true
    }
  }]
}

API key + secret pair#

json
1
2
3
4
5
6
7
8
{
  "name": "API Key Pair",
  "policy_type": "api_key",
  "fields": [
    {"name": "api_key", "generator": "hex", "config": {"length": 64}},
    {"name": "api_secret", "generator": "random", "config": {"length": 48, "charset": "safe"}}
  ]
}

Templated database username#

json
1
2
3
4
5
6
7
8
{
  "name": "DB Service User",
  "policy_type": "custom",
  "fields": [
    {"name": "username", "generator": "template", "config": {"template": "svc_{{random:8}}"}},
    {"name": "password", "generator": "random", "config": {"length": 24, "charset": "safe"}}
  ]
}

Template placeholders: {{random:N}} (alphanumeric), {{hex:N}}, {{uuid}}, {{timestamp}}, {{date:YYYY-MM-DD}}.

Ed25519 SSH key pair#

json
1
2
3
4
5
6
7
8
9
{
  "name": "SSH Host Key",
  "policy_type": "ssh_key",
  "fields": [{
    "name": "key",
    "generator": "ssh_keypair",
    "config": {"key_type": "ed25519", "comment": "scaivault-managed"}
  }]
}

The generated value contains both private_key and public_key sub-fields.

Attaching to a rotation policy#

bash
1
2
3
4
curl -X PATCH https://scaivault.scailabs.ai/v1/rotation/policies/rot_quarterly \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"secret_policy_id": "sp_db_passwords", "auto_generate": true}'

On each rotation, ScaiVault generates a fresh value from sp_db_passwords and writes it as the secret's new version.

Attaching to a single secret#

For secrets that have auto_generate: true set at the rotation level, you can override the recipe per secret:

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
curl -X PUT https://scaivault.scailabs.ai/v1/secrets/app/db/password \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {"password": "initial-value"},
    "options": {
      "rotation_policy_id": "rot_quarterly",
      "secret_policy_id": "sp_db_passwords"
    }
  }'
Updated 2026-05-17 13:26:51 View source (.md) rev 1