Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions PRIMITIVES.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ MCP servers, validated against a toolspec.
`pkg/tools/browserpolicy/` is the shared site-matching decision both the gate
and the tool's own pre-check consult. No dedicated controller yet (Phase A) —
identity-scoped sites and acting tools (click/type) arrive in later phases.
Phase B adds identity-bound login catalogs: the `directCredentials` credential
type (`pkg/platform/identity/directcred/`, sources `onepassword` and `secret`)
lets a BrowserToolbox bind an AgentIdentity and list its logins as
`{id, label, hosts}` onto `AgentSession.status` — the username/password/OTP
itself never reaches the model, the broker (`Resolve` errors unconditionally
for this type), or status.
- **Binaries:** `internal/cmd/streamclient/` (claims a streaming ToolCall via
the gateway); tool execution is otherwise driven from `internal/cmd/runner/`

Expand Down
10 changes: 10 additions & 0 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ does not relicense them under the project's license.
| TestSavantAI Prompt Injection Defender Base v2 ONNX model, [pinned revision](https://huggingface.co/testsavantai/prompt-injection-defender-base-v2-onnx/tree/a2109a5d583963f4962a9796d35315bdfed7c294) | Downloaded into the detector image at build time | [Apache License 2.0](images/promptinjection-detector/LICENSE) |
| Microsoft DeBERTa v3 Base, used as the detector model's base model | Detector image | [MIT License](third_party/licenses/DeBERTa-MIT.txt) |
| OWASP Top 10 for Agentic Applications 2026, by the OWASP GenAI Security Project | [`docs/references/OWASP-Top-10-for-Agentic-Applications-2026.pdf`](docs/references/OWASP-Top-10-for-Agentic-Applications-2026.pdf) | [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/legalcode); [source and attribution](docs/references/README.md) |
| pquerna/otp v1.5.0, by Paul Querna | Compiled into the runner binary (`pkg/platform/identity/directcred/secretsource`) | [Apache License 2.0](third_party/licenses/pquerna-otp-Apache-2.0.txt) |
| boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc, by Florian Sundermann | Compiled into the operator and runner binaries (via `pquerna/otp`, `pkg/platform/identity/directcred/secretsource`) | [MIT License](third_party/licenses/boombuler-barcode-MIT.txt) |
| 1Password Go SDK v0.4.1, by 1Password | Compiled into any binary linking the 1Password directcred source (`pkg/platform/identity/directcred/onepassword`) | [MIT License](third_party/licenses/onepassword-sdk-go-MIT.txt) |
| Extism Go SDK v1.7.1, by Extism | Pulled in by the 1Password Go SDK (wasm host runtime) | [BSD 3-Clause License](third_party/licenses/extism-go-sdk-BSD-3-Clause.txt) |
| wazero v1.11.0, by the wazero authors | Pulled in by the 1Password Go SDK (wasm runtime) | [Apache License 2.0](third_party/licenses/wazero-Apache-2.0.txt) |
| dylibso/observe-sdk (Go), by Dylibso | Pulled in by the 1Password Go SDK (via Extism) | [Apache License 2.0](third_party/licenses/observe-sdk-go-Apache-2.0.txt) |
| tetratelabs/wabin, by Tetrate | Pulled in by the 1Password Go SDK (via Extism) | [Apache License 2.0](third_party/licenses/wabin-Apache-2.0.txt) |
| ianlancetaylor/demangle, by The Go Authors | Pulled in by the 1Password Go SDK (via Extism/observe-sdk) | [BSD 3-Clause License](third_party/licenses/demangle-BSD-3-Clause.txt) |
| go.opentelemetry.io/proto/otlp v1.11.0, by the OpenTelemetry Authors | Pulled in by the 1Password Go SDK (via Extism/observe-sdk) | [Apache License 2.0](third_party/licenses/otel-proto-otlp-Apache-2.0.txt) |
| gobwas/glob v0.2.3, by Sergey Kamardin | Pulled in by the 1Password Go SDK (via Extism) | [MIT License](third_party/licenses/gobwas-glob-MIT.txt) |

Dependency metadata also identifies
[MPL 2.0](https://www.mozilla.org/en-US/MPL/2.0/) components (including
Expand Down
3 changes: 2 additions & 1 deletion cmd/oap/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import (
_ "github.com/authzed/openagentprimitives/pkg/authz/spicedb/relsource/imports" // completes the relsource claim table before `oap memory share` / `oap session capture`'s guarded writers are checked
"github.com/authzed/openagentprimitives/pkg/platform/deplogs"
_ "github.com/authzed/openagentprimitives/pkg/platform/identity/authkind/loader"
_ "github.com/authzed/openagentprimitives/pkg/platform/identity/credkind/imports" // register the static/oauth/federated credkind.Kinds the broker dispatches to via registry.Get
_ "github.com/authzed/openagentprimitives/pkg/platform/identity/credkind/imports" // register the static/oauth/federated credkind.Kinds the broker dispatches to via registry.Get
_ "github.com/authzed/openagentprimitives/pkg/platform/identity/directcred/onepassword" // register the "onepassword" directcred.Source the onepassword-service-account setup flow's Verify dispatches to via directcred.Get
_ "github.com/authzed/openagentprimitives/pkg/platform/identity/setup/builtins/loader"
)

Expand Down
95 changes: 95 additions & 0 deletions config/crds/agentprimitives.authzed.com_agentidentities.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,49 @@ spec:
items:
type: string
type: array
directCredentials:
description: |-
DirectCredentials is populated when type=directCredentials: a website
login the browser toolbox fills at use time. It never flows through the
broker — Resolve errors unconditionally — so it never projects into an
env var or header the way every other block here does. Valid ONLY on
AgentIdentity: the credential is authored on the bot's own identity,
not passed through from a human.
properties:
secretRef:
description: |-
SecretRef names the source's token Secret (key "token", onepassword)
or the host-keyed login Secret (secret).
properties:
key:
description: Key is the data key within the Secret holding
the value.
type: string
name:
description: Name is the Secret's name, in the referring
object's own namespace.
type: string
required:
- key
- name
type: object
source:
description: |-
Source names the login backend: onepassword resolves through a
1Password Connect token; secret reads a host-keyed login Secret
written directly.
enum:
- onepassword
- secret
type: string
vault:
description: Vault is the 1Password vault NAME; required
iff source is onepassword.
type: string
required:
- secretRef
- source
type: object
federated:
description: |-
Federated is populated when type=federated. The credential is MINTED
Expand Down Expand Up @@ -209,6 +252,7 @@ spec:
- oauth
- federated
- githubApp
- directCredentials
type: string
required:
- name
Expand Down Expand Up @@ -352,6 +396,57 @@ spec:
reflects.
format: int64
type: integer
pinnedVaults:
description: |-
PinnedVaults records, for each type=directCredentials credential whose
source has a vault concept (onepassword), the vault its backing token was
PROVEN to resolve to. The validity reconciler calls the directcred source's
Verify on first sight and records the vault id + name here; it re-verifies
only when the token changes (TokenFingerprint differs), so a rotated token
that now resolves to a DIFFERENT vault surfaces loudly as
Valid=False/DirectCredentialInvalid instead of silently listing another
vault's logins at the browser toolbox. A source with no vault concept
(secret) is never recorded here.

Operator-owned and derived: sorted by credential name and set once per
(credential, token) pair, so an unchanged token re-writes nothing and the
MergeFrom patch is a no-op. TokenFingerprint is a sha256 digest of the
token value, never the value itself.
items:
description: |-
PinnedVault is one entry of an identity's status.pinnedVaults — the vault a
type=directCredentials credential's token was proven to resolve to, pinned
once per token so a later rotation that redirects to a different vault is
caught rather than silently followed. Never carries the token value, only a
digest of it.
properties:
credential:
description: Credential is the credential name from spec.credentials[].name.
type: string
tokenFingerprint:
description: |-
TokenFingerprint is a hex sha256 digest of the backing token value at the
time the pin was written. It is the set-once key: a reconcile whose token
still hashes to this value carries the pin forward without re-verifying,
and a changed token forces a fresh Verify. It is a digest, never the token.
type: string
vaultID:
description: |-
VaultID is the backend's stable identifier for the pinned vault, as
returned by the source's Verify.
type: string
vaultName:
description: |-
VaultName is the human-readable vault name the backend confirmed. May
differ in case/whitespace from the credential's declared vault.
type: string
required:
- credential
- tokenFingerprint
- vaultID
- vaultName
type: object
type: array
resolvedCredentials:
description: ResolvedCredentials lists credential names whose Secret
+ key resolved.
Expand Down
Loading
Loading