# ~/.config/ontoref/schemas/ontoref-project.ncl — ProjectEntry contract.
# Installed by `just install-daemon`. Imported by per-project .ontoref/project.ncl files.

let KeyRole = [| 'admin, 'viewer |] in

let KeyEntry = {
  role  | KeyRole,
  hash  | String,
  label | String | default = "",
} in

# Maps ONTOREF_ACTOR value → role name declared in scopes/<role>.ncl.
# Example: { developer = "developer", ci = "cdci", ontoref = "ontoref" }
let actor_key_bindings_type = { _ | String } in

let VaultBackend = [| 'restic, 'kopia |] in

# Per-file recipient routing (optional). When `recipient_rules` is declared,
# bootstrap generates <vault_dir>/.sops.yaml from these definitions and sops
# encrypts each file with the union of recipient groups matching its path.
# Use case: multi-tenant projects where different clients/agents/teams
# decrypt different credential files within the same vault.
let recipient_group_type = { _ | Array String } in   # group → list of age1... pubkeys

let recipient_rule_type = {
  path   | String,                                   # path_regex relative to vault dir
  groups | Array String,                             # union of these recipient_groups
} in

let SopsConfig = {
  enabled | Bool | default = false,
  # Slug used for ~/.config/ontoref/vaults/<vault_id>/. Defaults to project slug when absent.
  vault_id | String | optional,
  # Restic or kopia. Switching requires re-initializing the local repo.
  vault_backend | VaultBackend | default = 'restic,
  # ZOT registry endpoint where src-vault/<vault_id>:latest is pushed/pulled.
  registry_endpoint | String | optional,
  # Paths to age public key files for each declared recipient (relative or absolute).
  age_key_paths | Array String | default = [],
  # Path to the master age private key (.kage). Overrides the global path in config.ncl.
  # Never store this inside the vault directory or the project root.
  master_key_path | String | optional,
  # ONTOREF_ACTOR → role name binding. Used by credential resolution to select the correct
  # sops-encrypted file in scopes/<role>.ncl before calling oras.
  actor_key_bindings | actor_key_bindings_type | default = {},
  # Per-file recipient routing — empty = use SOPS_AGE_RECIPIENTS env (legacy mode).
  recipient_groups | recipient_group_type    | default = {},
  recipient_rules  | Array recipient_rule_type | default = [],
} in

let ProjectEntry = {
  slug                | String,
  # Absolute local path to the project root. Empty string for push_only projects.
  root                | String,
  # Import paths for nickel export on this project's NCL files (local projects only).
  nickel_import_paths | Array String | default = [],
  # Auth keys for this project. Empty = no auth required.
  keys                | Array KeyEntry | default = [],
  # Remote URL for push_only projects (git, SSH, HTTPS). Informational — not accessed by daemon.
  remote_url          | String | default = "",
  # When true: no local file watch, no NCL import. Project pushes ontology via POST /sync.
  push_only           | Bool   | default = false,
  # Registry credential vault configuration. Absent = no registry credentials declared.
  sops                | SopsConfig | optional,
} in

{
  make_project        = fun fields => fields | ProjectEntry,
  make_remote_project = fun fields => (fields & { push_only = true, root = "", nickel_import_paths = [] }) | ProjectEntry,
}
