Scoping to collections

Projecting part of an environment, and why the rest is never read.

Most environments hold keys for more than one thing. A resource can project only the collections a workload needs, so the service that talks to the database does not also receive your payment keys.

Project only some of it

apiVersion: connectors.orcakey.sh/v1alpha1
kind: OrcaKeySync
metadata:
  name: orcakey-secrets
spec:
  # <your-project> / <your-environment>
  environmentId: <your-environment-id>
  apiBaseUrl: https://api.orcakey.sh
  tokenRef:
    name: orcakey-token
  scope:
    include: [database]
  intervalSeconds: 300

Only keys filed under database appear in the Secret. Everything else in <your-environment> is absent.

If most of the environment belongs and a little does not, say that instead:

apiVersion: connectors.orcakey.sh/v1alpha1
kind: OrcaKeySync
metadata:
  name: orcakey-secrets
spec:
  # <your-project> / <your-environment>
  environmentId: <your-environment-id>
  apiBaseUrl: https://api.orcakey.sh
  tokenRef:
    name: orcakey-token
  scope:
    exclude: [stripe]
  intervalSeconds: 300

Setting both is refused rather than resolved by a precedence rule you would have to remember. Keys filed under no collection are named (uncollected) and can be included or excluded like any other — so every key is always in exactly one collection, and (uncollected) is a collection like the rest rather than a gap between them.

A scope names collections, never keys

There is no way to scope to a key. include and exclude take collection names, and a key comes along because of where it is filed.

So to project one key on its own, give it a collection of its own. File it somewhere new, and scope to that:

apiVersion: connectors.orcakey.sh/v1alpha1
kind: OrcaKeySync
metadata:
  name: orcakey-secrets
spec:
  # <your-project> / <your-environment>
  environmentId: <your-environment-id>
  apiBaseUrl: https://api.orcakey.sh
  tokenRef:
    name: orcakey-token
  scope:
    include: [registry]
  intervalSeconds: 300

The rest of the environment is unaffected — keys you did not move stay where they are, and a sibling resource can take everything else with exclude: [registry], because (uncollected) still covers the ones you left alone.

This is worth stating because it is a real difference from tools that filter by key name or prefix. Porting one of those is not a rename: a KEYS_* pattern becomes a collection, and the keys it used to match have to be filed into it.

The keys outside the scope are never read

orcakey.sh applies the filter. The operator does not fetch the whole environment and keep the part it wants, so values outside the scope are never sent, never reach your cluster, and never appear in your audit trail as having been read.

The difference is invisible in the result and decisive in an incident: after a token leaks, “what did this actually see” has an answer.

Changing your mind

Edit the scope and apply it again. The next sync converges: keys newly in scope appear, keys newly out of scope are removed, and the rest are untouched. Nothing needs deleting and recreating.

Removing a collection from the scope removes those keys from the cluster, which is how you take access away.

A collection that does not exist

The resource reports ScopeInvalid and projects nothing.

Treating an unknown collection as an empty one would turn a typo into a Secret with no keys and a workload that starts with nothing, explained nowhere.