Skip to content

Superseded

The canonical Bluefly Authentication & Secrets Constitution is:

STD-SEC-001 — Bluefly Authentication & Secrets Constitution


1. Prime Directive

Do not wrap every call with 1Password.

GITLAB_TOKEN=op://<vault>/<item-id>/token
GITLAB_TOKEN='op://<vault>/<item-id>/token' op run -- sh -c 'COMPOSER_AUTH="{\"gitlab-token\":{\"gitlab.com\":\"$GITLAB_TOKEN\"}}" composer install'

1Password protects and delivers secrets. Target platforms authenticate and authorize their identities. Bluefly governs policy and execution. Keep these facts separate: Authentication (who or what is making the request?), Authorization (may that principal perform this operation on this target?), Execution authority (which system is responsible for performing the operation?). A successful 1Password lookup does not prove GitLab authorization. A valid GitLab token does not prove permission to merge a protected branch. A working SSH identity does not prove permission to mutate Oracle. A CI job token does not automatically grant cross-project package access. A failed command proves only that that invocation failed. Never turn one failure into an invented infrastructure diagnosis.

2. Bluefly Authority Map

Secret system of record: 1Password. Git repositories, MRs, packages, releases, CI/CD: GitLab. Shared CI implementation: gitlab_components. Production execution: Oracle. Work authorization/execution ledger: Beads/Gas City. Kubernetes authorization: Kubernetes RBAC. Git/SSH authentication: OpenSSH + 1Password SSH Agent where applicable. GitLab permissions: GitLab roles/policies/branch protections/token controls. Long-lived application secret retrieval: 1Password Connect/Service Account/supported upstream integration. Architecture and policy: Bluefly. Canonical doctrine: BluCity-Docs in GitLab.

Rule: use the owner, do not create another owner. If GitLab owns GitLab authorization, diagnose it in GitLab. If 1Password owns secret delivery, configure 1Password. If Kubernetes owns workload authorization, configure RBAC. If an upstream capability already solves the requirement, Bluefly composes it instead of rebuilding it.

Separation of duties, stated as roles rather than systems:

1PASSWORD        secret system of record and delivery
BLUEFLY          naming, policy, orchestration, execution governance
TARGET PLATFORM  authorization and target credential lifecycle
AGENT            bounded consumer of capability
HUMAN OPERATOR   human operator, not machine credential broker

3. Identity Preference Order

Use the least persistent identity that supports the exact operation.

  • Tier 1 — Native short-lived identity: CI_JOB_TOKEN, GitLab ID tokens/OIDC where supported, native cloud workload identity, other upstream ephemeral workload credentials. Short-lived wins over durable. Do not create a PAT merely because a native identity requires correct allowlisting/permissions.
  • Tier 2 — 1Password Service Account: for non-human processes requiring governed 1Password access where Connect is unnecessary.
  • Tier 3 — 1Password Connect: for long-lived services/infrastructure needing an application-facing secrets API. The Connect cache is acceptable — it's 1Password-owned behavior, not a Bluefly credential cache.
  • Tier 4 — Durable target-platform credential: only after proving the required operation cannot use an appropriate short-lived identity. Required evidence: NATIVE_IDENTITY_TESTED=YES / NATIVE_IDENTITY_SUPPORTED=NO / DURABLE_IDENTITY_REQUIRED=YES / LEAST_PRIVILEGE=YES / DELIVERY_PATH=1PASSWORD. Convenience is not evidence.

4. The Bluefly Authentication Algorithm

IDENTIFY PRINCIPAL -> AUTHENTICATE ONCE -> REFERENCE SECRET -> 1PASSWORD DELIVERS
  -> TARGET AUTHENTICATES / AUTHORIZES -> EXECUTE THROUGH OWNER -> REUSE AUTHORITY

Before modifying authentication, establish: OPERATION= / TARGET= / PRINCIPAL= / IDENTITY_TYPE= / AUTH_PATH= / AUTHENTICATED= / TARGET_ROLE= / AUTHORIZED= / EXACT_DENIAL=. Then: (1) identify the exact operation, (2) identify the exact principal that should perform it, (3) identify the already-configured authentication path, (4) reuse that path, (5) perform one bounded test, (6) determine the failure classification, (7) fix the owning layer, (8) only then escalate. Never begin authentication debugging by searching for another token.

5. GitLab Token Truth Protocol (MANDATORY)

Only GitLab may establish that a GitLab credential is expired, revoked, inactive, insufficiently scoped, or unauthorized. These do NOT prove expiration: op read failed, op authorization timeout, 1Password not signed in, GLAB_TOKEN/GITLAB_TOKEN missing, glab auth failure, HTTP 401, HTTP 403, CI job failed, package publish failed, MR merge denied.

Classify accurately: - op read failed => SECRET_RETRIEVAL_FAILED - token never loaded => TOKEN_NOT_TESTED - GitLab 401 => GITLAB_AUTHENTICATION_FAILED => EXPIRATION_NOT_PROVEN - GitLab 403 => GITLAB_AUTHORIZED_BUT_FORBIDDEN or insufficient policy/scope/role => EXPIRATION_NOT_PROVEN

For a PAT, GitLab itself is authoritative — after retrieving the intended credential without printing it, use GitLab's self-inspection endpoint (GET /api/v4/personal_access_tokens/self with the token header, silent/bounded, pipe through jq for id/name/active/revoked/expires_at/last_used_at/scopes only). Interpret mechanically: - active=true + revoked=false + expires_at>now => TOKEN_VALID - revoked=true => TOKEN_REVOKED - active=false => TOKEN_INACTIVE - expires_at<=now => TOKEN_EXPIRED

Never report TOKEN_EXPIRED without target-platform evidence.

GitLab Private-Resource 404 Rule

A 404 on a private GitLab resource (project, MR, issue, package) is not proof the resource does not exist. GitLab conceals private-resource existence from callers it has not authenticated and authorized — an unauthenticated or insufficiently scoped request gets the identical 404 a real absence would produce.

if AUTHENTICATED != YES
and GitLab returns 404:

GITLAB_AUTHENTICATION_OR_AUTHORIZATION_FAILED=UNRESOLVED
EXISTENCE_DISPROVEN=NO

Never conclude PROJECT_NOT_FOUND, MR_NOT_FOUND, ISSUE_NOT_FOUND, or PACKAGE_NOT_FOUND from a 404 against a private resource alone.

Required diagnostic sequence before interpreting the response:

  1. Was a credential actually presented?
  2. Did GitLab authenticate the principal?
  3. Was the principal authorized for that resource?
  4. Only then interpret the resource response.

6. GitLab Identity Roles

Do not treat all GitLab credentials as interchangeable — each has a defined purpose: GITLAB_OPERATOR_IDENTITY, GITLAB_AGENT_IDENTITY, GITLAB_PACKAGE_REGISTRY_IDENTITY, GITLAB_CI_JOB_IDENTITY. Do not substitute one for another because auth failed, do not search 1Password for "a token that works," do not promote the most-privileged credential as a debugging shortcut. Before use establish: TOKEN_PURPOSE= / TOKEN_SOURCE= / TOKEN_IDENTITY= / EXPECTED_SCOPE= / TARGET_OPERATION=. Secret values are never included.

7. GitLab CI/CD

CI is non-interactive. Preferred order: CI_JOB_TOKEN -> GitLab native ID token/workload identity -> narrowly scoped durable machine identity. For CI_JOB_TOKEN cross-project access verify: SOURCE_PROJECT= / TARGET_PROJECT= / ENDPOINT_SUPPORTS_CI_JOB_TOKEN= / TARGET_JOB_TOKEN_ALLOWLIST= / TRIGGERING_USER_ROLE= / AUTHORIZED=. Forbidden: "CI_JOB_TOKEN failed -> create PAT". Required: "CI_JOB_TOKEN failed -> determine exact denial -> fix allowlist/permission/endpoint contract -> escalate identity type only if the operation truly requires it."

8. Shared CI Owns Shared Authentication Plumbing

SHARED_CI_OWNER=gitlab_components. Individual projects must not independently recreate npm/Composer/GitLab-Package-Registry/container-registry authentication, release/deployment credentials, token-selection logic, or promotion-MR credentials. If multiple projects need the same auth behavior, it belongs in the shared CI layer — projects configure the capability, they do not fork it.

9. 1Password Operating Model

1Password is Bluefly's canonical secret system of record — not its authorization engine. Use the narrowest supported mechanism. Interactive workstation: prefer existing 1Password session -> Shell Plugin/bounded op invocation -> target CLI; don't require repeated op signin; don't globally export durable credentials into every shell. SSH: 1Password SSH Agent -> OpenSSH -> target host authorization; never copy a private key just because an agent can't immediately authenticate. Non-human access: Service Account or 1Password Connect per workload. Kubernetes: use upstream 1Password integrations first (Secrets Injector for process-level injection, Operator only if a Kubernetes Secret object is actually required) — don't build a Bluefly secrets sync controller when upstream satisfies it.

Authenticate once; do not wrap every call. Once a target credential is bound into the environment for the session, invoke the target CLI directly. Re-resolving the same secret on every invocation is not additional security: it adds latency, triggers repeated authorization prompts, and is precisely the friction Section 15 classifies as an architecture defect.

AUTHENTICATE_ONCE=YES
DO_NOT_WRAP_EVERY_CALL=YES

For GitLab specifically: bind GITLAB_TOKEN from its 1Password reference once per session, then run glab bare. Do not prefix each invocation with op run, op plugin run, or blu 1p, and do not source ~/.config/op/plugins.sh to make that wrapping automatic. Verify the binding at the target rather than at the secret store — glab auth status reporting Token found in environment variable GITLAB_TOKEN is the proof that further wrapping is redundant.

The rule generalizes to every target: wrap once at session or process start, never per command. A bounded op invocation is the mechanism that establishes the session, not a prefix carried by each subsequent command.

10. Oracle Production Rule

Oracle executes; Oracle does not become a secret store. Long-lived runtime services should consume credentials through supported machine integrations. Don't turn op read/op run into an application secrets API, don't maintain plaintext runtime credential files as architecture, don't create a Bluefly credential cache or another secret broker. If repetitive secret retrieval is needed for a long-running service, configure the appropriate upstream machine integration instead.

11. Secret References, Not Secret Values

Source/config contains references, never resolved values. Allowed conceptually:

gitlab: token_ref: ${GITLAB_OPERATOR_TOKEN_REF}

Forbidden:

gitlab: token: glpat-actual-secret

Even op:// references should not be copied throughout the estate — use semantic names (GITLAB_OPERATOR_TOKEN_REF, GITLAB_PACKAGE_REGISTRY_TOKEN_REF, ORACLE_MACHINE_IDENTITY_REF) bound to concrete 1Password objects only at the environment/configuration layer. Do not spread concrete object IDs/paths through prompts, Beads, agent context, architecture docs, source, CI output, receipts, or debugging transcripts.

This Constitution governs 1Password/operator-side authority (who may hold and reference a secret). It does not govern how a secret reaches a Gas City execution surface (order exec, provider script, hook, sling) — that command-construction boundary (never interpolate untrusted text into sh -c, orchestrator-side env stripping of secret-looking keys, direct-exec over shell-string) is Gas City's own doctrine, reproduced at gas-city-command-execution-trust-boundaries.md.

12. Evergreen Doctrine vs. Environment Binding

The Constitution defines rules, not an inventory of today's machines. Do not put workstation paths, token IDs, current PAT names, current Oracle IPs, temporary ports, current 1Password UUIDs, generated configuration, or one incident's runtime telemetry into evergreen doctrine — those facts belong to the system that owns them (GitLab, 1Password, IaC, runtime configuration, environment bindings). Stale operational facts must not become permanent agent instructions.

13. Context Is a Security Boundary

Agents consume context as executable truth, so stale context can create real security defects (retired token name, obsolete op:// path, old GitLab identity, dead SSH path, superseded CI auth pattern, retired host, old service endpoint, duplicate credential alias). When encountered: STALE_CONTEXT_FOUND=YES / CURRENT_AUTHORITY= / REPLACEMENT= / OWNER=. Do not work around stale context — correct or retire it at its owner. Historical evidence may remain historical; it must not masquerade as current configuration.

14. Agent Authentication Contract

Every Bluefly agent MUST: identify the operation; identify the intended principal; reuse the existing authentication path; test once; distinguish retrieval/authentication/authorization; diagnose the system enforcing the denial; use the least persistent appropriate identity; keep secret values out of output; fix the owning layer; prefer upstream mechanisms; execute once evidence is sufficient.

Agents MUST NOT: enumerate vaults looking for a credential that works; search token names as an authentication strategy; print tokens or private keys; dump environments containing secrets; place a resolved secret in a command's literal arguments (argv) when that command runs through any wrapper — DDEV, a CI runner, a shell tool — whose error path may echo the attempted command line (this leaks the value even when the agent never issues its own print/echo; proven 2026-09-03, ledger/2026-08-25__credential-exposure-register__OPEN.md P0-7: ddev exec env SECRET=<value> <cmd> failed non-zero on an unrelated warning and DDEV echoed the full command line — pass secrets through the process environment or stdin instead, never as an argument string); create plaintext .env/.op-env secret snapshots; globally export durable credentials; create a new PAT because one request failed; duplicate a credential under another name; invent a credential broker; create a Bluefly secret cache; repeatedly trigger biometric/sign-in prompts; ask the operator to paste a credential; infer authorization from authentication; infer expiration from a 401; call 1Password unavailability "GitLab token expiration"; create project-specific authentication plumbing already owned upstream or by gitlab_components.

14.1 Discovering a credential in a file

If an agent discovers a credential at rest, it MUST NOT cat, print, echo, relay, paste, report its value, or store it in a Bead, prompt, or receipt. Report only:

TARGET=  PRINCIPAL=  LOCATION=  EXPOSURE_CONFIRMED=
ROTATION_OWNER=  AUTOMATED_ROTATION_AVAILABLE=

Then execute the rotation lifecycle through the owning platform (§16).

15. Authentication Failure Is an Engineering Signal

Repeated authentication friction (repeated signin/biometrics/op run, token copying, PAT proliferation, manual secret files, project-specific auth variables, credential searching, custom token brokers) is not an invitation to add another workaround. Return AUTH_ARCHITECTURE_DEFECT=YES, identify the owner. Goal: make the next invocation ordinary.

16. Rotation

Rotation belongs to the system that issues the credential: TARGET PLATFORM issues/rotates/revokes -> 1PASSWORD stores/delivers the durable credential when required -> ENVIRONMENT BINDING retains a stable semantic reference -> CONSUMER receives the current credential through the approved delivery path. GitLab credentials are rotated/revoked in GitLab. Rotation isn't complete merely because a value changed in 1Password — the old credential must be invalid where it was issued and all consumers must use the replacement. Rotation should never require editing dozens of repositories.

17. Authorization Receipt

Authentication-related execution returns only useful evidence: OPERATION= / TARGET= / PRINCIPAL= / IDENTITY_TYPE= / AUTH_PATH= / AUTHENTICATED=YES|NO / TARGET_ROLE= / TARGET_POLICY= / AUTHORIZED=YES|NO / EXACT_DENIAL= / NATIVE_IDENTITY_TESTED= / DURABLE_CREDENTIAL_REQUIRED= / TOKEN_STATE_VERIFIED_BY_TARGET= / SECRET_VALUE_EXPOSED=NO / SECRET_COPIED=NO / NEW_SECRET_STORE_CREATED=NO / OWNER= / NEXT_EXECUTABLE_ACTION=. Resolved credentials never appear in receipts.

18. BluCity-Docs Authority

This doctrine is authoritative because it's committed through governed Git history, not because of the machine holding a checkout. LOCAL_CHECKOUT != AUTHORITY, NAS_CHECKOUT != AUTHORITY, ORACLE_CHECKOUT != AUTHORITY, GITLAB_BLUCITY_DOCS = SOURCE_AUTHORITY. Local/NAS/Oracle copies are working/deployed representations and may not contain unique authoritative doctrine. If copies disagree, converge against Git authority while preserving any unique legitimate work before cleanup.

19. Upstream-First Rule

Before creating authentication or secret-management code: (1) search current upstream documentation, (2) search the upstream implementation, (3) determine whether the capability already exists, (4) configure the existing capability, (5) compose existing capabilities where necessary, (6) only after a proven capability gap may Bluefly own new implementation. Test: UPSTREAM_CAPABILITY_CHECKED=YES / EXISTING_BLUEFLY_CAPABILITY_CHECKED=YES / CAPABILITY_GAP_PROVEN=YES / CUSTOM_IMPLEMENTATION_REQUIRED=YES. Without all four: CUSTOM_IMPLEMENTATION=NO.

20. Fast Agent Contract

Condensed restatement of the above, for quick agent reference — same rules, no new content: 1Password protects/delivers secrets, target platforms authenticate/authorize, Bluefly governs policy/execution. Authenticate once, reuse authority, least persistent identity, reference not copy secrets, never search for "another token that works," GitLab alone establishes GitLab token expiration, op failure != expiration, 401/403 != expiration, CI_JOB_TOKEN first for CI, reuse existing 1Password session on workstations, Service Accounts/Connect for long-lived runtime, Oracle executes, shared CI belongs in gitlab_components, authentication != authorization, establish OPERATION/TARGET/PRINCIPAL/AUTH_PATH/AUTHENTICATED/TARGET_ROLE/AUTHORIZED/EXACT_DENIAL before declaring AUTH_BLOCKED, no printing/caching/snapshotting/exporting credentials, no PATs as debugging tools, no credential brokers/caches, configure/compose upstream before rebuilding.

21. Per-Role Machine Identity Requirement

Every standing autonomous role (BLU, MAYOR, REFINERY, SENTINEL, FOUNDRY, DRUPAL, WITNESS, HARBORMASTER, and any future standing role) requires its own machine identity: a named identity, a 1Password principal bound to that identity (Tier 1/2/3 per §3), a GitLab principal, an explicit auth scope, and a documented rotation method. The full per-role table is the Machine Identity Catalog; this section states the invariant the catalog exists to satisfy.

  • No standing role ever borrows another role's machine identity — including the human operator's own interactive session. A role authenticating as Thomas (or as any other role) to get past a missing or misconfigured identity is AUTH_ARCHITECTURE_DEFECT=YES (§15), not a workaround.
  • Autonomous agent pattern: agent machine identity → 1Password Service Account / Connect / SDK (§3 Tier 2/3) → semantic secret reference (§11) → target credential → target authorization. No interactive step anywhere in this chain.
  • Human pattern (Thomas): interactive 1Password session (§9), reused across a working session per the Prime Directive — never scripted into an agent's standing identity.
  • These two patterns never cross: an agent that needs interactive op signin to function has the wrong identity tier, and a human workflow that depends on a Service Account token is misusing infrastructure credentials for a task that should stay interactive.
  • A role with no entry in the Machine Identity Catalog, or an entry marked not-yet-provisioned, has no standing authority to act — route that role's work through the human operator or an already-provisioned role until provisioning closes the gap.

22. Process and Status Output Is a Secret-Bearing Surface

A running process publishes two things to every local principal: its argument vector and, to root and same-user principals, its environment. Any tool that renders either is therefore a secret-bearing surface, and reading it is subject to the same rules as op read: bounded, field-scoped, never verbatim into a transcript, receipt, Bead, mail, or event.

The 2026-09-03 P0-7 precedent (§14) proved the argv leak through a wrapper's error path. The 2026-09-20 precedent proved it through ordinary status inspection: a Gas City agent session launched with tmux -e VAR=VALUE reproduced the value inside systemctl --user status, and a cloudflared connector started with --token <value> reproduced it in pgrep -a. No agent printed a secret. The surface did.

22.1 Surfaces that embed argv or environment

Tool What it reprints Note
ps, ps aux, ps -ef, ps -o args/command full argv of every process argv is world-readable on Linux and macOS
pgrep -a, pgrep -f, pkill -f (echo on failure) argv -a prints it; -f matches against it
/proc/<pid>/cmdline, /proc/<pid>/environ argv; environment environ readable by same user and root
systemctl status <unit> CGroup process tree with full command lines user and system managers alike
systemctl show <unit> (unfiltered) Environment=, ExecStart= with argv, EnvironmentFiles= paths --property whitelist required
systemctl cat <unit>, journalctl -u <unit> unit text incl. Environment=; startup lines that echo the command
docker inspect, docker ps --no-trunc, docker compose config Config.Env, Config.Cmd, Args; resolved environment: and command: compose config resolves .env into the output
docker exec <c> env, kubectl exec ... env, kubectl get pod -o yaml container environment; pod spec env values
launchctl print <domain>/<label>, launchctl dumpstate environment = { ... } block and program arguments macOS
tmux show-environment, tmux display -p '#{...}' session environment
crontab -l, cat of unit/compose/plist files literal KEY=VALUE and --token lines file surfaces, same rule
set, env, export -p, declare -p, printenv the whole shell environment already forbidden by §14 ("dump environments")

22.2 Safe inspection pattern

Inspect fields, not blobs. The pattern is: whitelist the fields → strip anything that is a command line or environment → pipe the remainder through the redaction filter. In order of preference:

  1. Field whitelist (primary control).
  2. Process liveness: pgrep -x <comm> (PIDs only), ps -o pid,comm,etime,stat -p <pid>. Never -o args, -o command, -o cmd, or a bare ps aux.
  3. systemd: systemctl is-active <unit>, systemctl is-failed <unit>, systemctl show <unit> --property=ActiveState,SubState,MainPID,ExecMainStartTimestamp,NRestarts,Result. Never bare status, never --property=Environment, ExecStart, ExecStartPre.
  4. Docker: docker ps --format '{{.Names}} {{.Status}}', docker inspect --format '{{.State.Status}} {{.State.Health.Status}}' <c>. Never bare docker inspect, never --no-trunc, never compose config without --no-interpolate.
  5. Kubernetes: kubectl get pod <p> -o jsonpath='{.status.phase}'; env questions are answered by kubectl get pod -o jsonpath='{.spec.containers[*].env[*].name}' (names only).
  6. launchd: launchctl list <label> (pid/status only), never launchctl print.
  7. Journal: journalctl -u <unit> -n 50 --no-pager | redact-status-output.sh.
  8. Redaction filter (backstop). When a verbose surface is genuinely required (diagnosing a launch failure), pipe it through redact-status-output.sh (BluCity-Packs foundation/security/assets/scripts/), which replaces the value of every -e KEY=VALUE pair, every KEY=VALUE whose key contains TOKEN|SECRET|PASSW|API_KEY|PRIVATE|CREDENTIAL, every --token/--password-class flag argument, Bearer values, and bare credential shapes (glpat-, gldt-, ghp_, sk-, xox?-, eyJ…) with <redacted>. Over-redaction is acceptable; a filter that lets a value through is a defect to be fixed in the filter, never worked around.
  9. Never paste raw output from a §22.1 surface into a Bead, mail, event, receipt, MR, wiki page, or chat reply. If it has already happened, the exposure is ledger-scoped, not transcript-scoped, and is classified as such.

The same test as §5 applies: a status surface that appears clean has not been proven clean by eyeballing. Prove it by the field whitelist or the filter.

22.3 Launcher rule: tokens travel by file or inherited environment, never by argv

Every process that starts another Bluefly process with a credential — Gas City supervisor and providers (tmux, pre_start, session_setup, order exec), systemd units, docker/compose, launchd, CI runners, shell helpers — MUST deliver the credential through one of:

  • an environment file owned by the service user, mode 0600, loaded by the launcher (EnvironmentFile= in systemd; env_file: in compose; set -a; . <file>; set +a inside a pre_start that runs before the session command is exec'd; tmux set-environment -t <session> KEY VALUE after new-session, which sets the value in the tmux server, not argv);
  • a credential file the consumer reads itself (--credentials-file, --token-file, --password-file, a 1Password Connect/Service Account path per §3), mode 0600;
  • inherited environment from a parent that itself obtained the value by one of the above, with the orchestrator-side secret-key stripping from gas-city-command-execution-trust-boundaries.md left intact;
  • stdin, for one-shot consumers.

MUST NOT: tmux new-session -e KEY=VALUE, docker run -e KEY=VALUE (use --env-file or -e KEY with no =, which forwards from the launcher's environment without placing the value in argv), cloudflared ... --token <value>, ExecStart=... --password <value>, Environment=KEY=VALUE in a unit file (that is argv-adjacent: systemctl show prints it), env KEY=VALUE cmd under any wrapper, or sh -c "KEY=VALUE cmd".

A launcher that passes a credential by argv has AUTH_ARCHITECTURE_DEFECT=YES (§15) with OWNER= the launcher's maintainer — for Gas City sessions that is Gas City upstream (contribute the fix; do not fork a Bluefly launcher), and until it lands the pack-side gate foundation/security/formulas/session-safety-gate.toml (check-tmux-env-args) MUST sit on the supervisor's launch path, not merely exist in the pack.

22.4 Receipt fields

Any receipt that includes process/status evidence adds:


Constitutional Invariants

  1. Authenticate once.
  2. Reuse existing authenticated authority.
  3. Use the least persistent identity capable of the operation.
  4. 1Password is Bluefly's canonical secret system of record.
  5. Target platforms remain authoritative for their identities and permissions.
  6. Authentication and authorization are separate facts.
  7. A failed invocation proves only that invocation failed.
  8. GitLab alone establishes GitLab-token state.
  9. 401 does not prove expiration.
  10. 403 does not prove expiration.
  11. 1Password failure does not prove GitLab failure.
  12. No PAT proliferation as a debugging strategy.
  13. No secret values in source, logs, prompts, receipts or agent context.
  14. No custom Bluefly secret cache or credential broker.
  15. Shared CI authentication belongs in gitlab_components.
  16. Oracle executes; Oracle does not become a secret store.
  17. Use official 1Password machine and Kubernetes integrations first.
  18. Evergreen doctrine contains rules, not temporary machine facts.
  19. Stale operational context is actively retired.
  20. If upstream owns the capability, configure or compose it before creating Bluefly code.
  21. Every authentication incident ends configured, verified, or escalated to the actual owner.
  22. Once evidence is sufficient, execute instead of generating more process artifacts.
  23. Process argv and environment are secret-bearing surfaces: inspect by field whitelist or redaction filter; launch with files or inherited environment, never argv.

Operating Maxim: Authenticate once. Reference secrets. Reuse authority. Verify at the owner. Prefer upstream. Execute. A mature authentication architecture is one in which agents rarely need to think about credentials — the principal is already known, the credential remains where it belongs, the target platform determines authorization, the execution plane performs the operation, and when something fails the agent diagnoses the owning layer instead of manufacturing another credential, workaround, or piece of infrastructure.