# Policy Bundle

## Retrieve

`client.PolicyBundle.Get(ctx, query) (*Response, error)`

**get** `/policy/bundle`

Returns the effective Policy Bundle for the user identified by the
zone-issued resource-scoped token. When no user-scope binding exists,
one will be generated from the default set.

The response body is a binary archive in the codec selected via the
`Accept` header. The only codec supported today is
`application/vnd.keycard.policy-bundle.v1+tar+gzip`. Clients SHOULD send
an explicit `Accept` header; absent one, the server defaults to the
tar+gzip codec.

Supports conditional fetch via `If-None-Match`: when the supplied ETag
matches the current bundle, the server responds `304 Not Modified` with
no body.

### Parameters

- `query PolicyBundleGetParams`

  - `IfNoneMatch param.Field[string]`

    Conditional fetch ETag. If the supplied value matches the current
    bundle ETag, the server returns `304 Not Modified` with no body.

  - `XClientRequestID param.Field[string]`

    Unique request identifier specified by the originating caller and passed along by proxies.

### Returns

- `type PolicyBundleGetResponse interface{…}`

### Example

```go
package main

import (
  "context"
  "fmt"

  "github.com/keycardai/keycard-go"
  "github.com/keycardai/keycard-go/option"
)

func main() {
  client := keycard.NewClient(
    option.WithAPIKey("My API Key"),
  )
  policyBundle, err := client.PolicyBundle.Get(context.TODO(), keycard.PolicyBundleGetParams{

  })
  if err != nil {
    panic(err.Error())
  }
  fmt.Printf("%+v\n", policyBundle)
}
```

## Update

`client.PolicyBundle.Update(ctx, body, params) (*Response, error)`

**put** `/policy/bundle`

Accepts an edited Policy Bundle archive and applies it as the active
user-scope PolicySetVersion for the calling user.

The user's policy set is seeded from the system-default policies on
first access, forked into customer-owned policies; a user bundle
therefore contains only customer-owned policies. Applying an edit
creates a new version of the affected policy, and a `new_policy` entry
adds a further customer-owned policy. Platform-owned catalog policies
are never edited in place by this operation.

The request body codec is determined from `Content-Type`. The only codec
supported today is `application/vnd.keycard.policy-bundle.v1+tar+gzip`.

Supports optimistic concurrency via `If-Match`: when supplied, the server
applies the bundle only if the supplied ETag matches the current bundle
ETag; otherwise responds `412 Precondition Failed`.

On success the server returns the materialized bundle (in the same
codec) and its new `ETag`.

### Parameters

- `body Reader`

  tar+gzip Policy Bundle archive. `manifest.json` is **required**
  (see `PolicyBundleManifest`); `schema.cedarschema` is **optional
  and ignored** — the server validates against its attested schema
  for `manifest.schema.version`. The manifest's `policies[]` list is
  authoritative for the resulting set: each entry must have a
  matching `policies/<public_id>.cedar` (or, for a `new_policy`
  entry, `policies/<new_policy>.cedar`) member, and a member with no
  manifest entry is dropped. Only the `sha` fields are advisory and
  recomputed server-side. Duplicate or unrecognized entries are
  rejected with `bundle_invalid`. See the **PolicyBundle** tag for
  the layout.

- `params PolicyBundleUpdateParams`

  - `IfMatch param.Field[string]`

    Header param: Optimistic concurrency ETag. When supplied, the server applies the
    bundle only if the value matches the current bundle ETag; otherwise
    responds `412 Precondition Failed`.

  - `XClientRequestID param.Field[string]`

    Header param: Unique request identifier specified by the originating caller and passed along by proxies.

### Returns

- `type PolicyBundleUpdateResponse interface{…}`

### Example

```go
package main

import (
  "bytes"
  "context"
  "fmt"
  "io"

  "github.com/keycardai/keycard-go"
  "github.com/keycardai/keycard-go/option"
)

func main() {
  client := keycard.NewClient(
    option.WithAPIKey("My API Key"),
  )
  policyBundle, err := client.PolicyBundle.Update(
    context.TODO(),
    io.Reader(bytes.NewBuffer([]byte("some file contents"))),
    keycard.PolicyBundleUpdateParams{

    },
  )
  if err != nil {
    panic(err.Error())
  }
  fmt.Printf("%+v\n", policyBundle)
}
```

## Reset

`client.PolicyBundle.Reset(ctx, body) error`

**delete** `/policy/bundle`

Archives the PolicySet for the calling user (if any),
causing subsequent `GET /policy/bundle` requests to fall back to the
default user policies. Idempotent: returns `204 No Content` even when no
user-scope binding exists.

### Parameters

- `body PolicyBundleResetParams`

  - `XClientRequestID param.Field[string]`

    Unique request identifier specified by the originating caller and passed along by proxies.

### Example

```go
package main

import (
  "context"

  "github.com/keycardai/keycard-go"
  "github.com/keycardai/keycard-go/option"
)

func main() {
  client := keycard.NewClient(
    option.WithAPIKey("My API Key"),
  )
  err := client.PolicyBundle.Reset(context.TODO(), keycard.PolicyBundleResetParams{

  })
  if err != nil {
    panic(err.Error())
  }
}
```
