You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/reference/contrib-plugins.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -205,18 +205,18 @@ Maps a [`TransactionContext`][tx] to a credential key (e.g., a tenant ID, sessio
205
205
206
206
A successful return must be a non-empty string. Return [`ErrMissingContextData`](#sentinel-errors) if the transaction lacks enough information to resolve a key.
207
207
208
-
### `ResolveFromContext`
208
+
### `ResolveCredentialKey`
209
209
210
210
```go
211
-
funcResolveFromContext(
211
+
funcResolveCredentialKey(
212
212
ctx context.Context,
213
213
tx sdk.TransactionContext,
214
214
dataField string,
215
215
resolver KeyResolver,
216
216
) (string, error)
217
217
```
218
218
219
-
Shared helper that providers call instead of reading `tx.Data` directly. It implements a strict fallback chain:
219
+
Shared helper for credential-selection keys (for example, Microsoft `TenantID`). It implements a strict fallback chain:
220
220
221
221
1. If `tx.Data[dataField]` is present and is a valid non-empty string, return it (explicit connector override).
222
222
2. If `tx.Data[dataField]` is present but has the wrong type or is empty, return [`ErrInvalidContextData`](#sentinel-errors). Malformed overrides never fall through to the resolver.
@@ -622,8 +622,8 @@ Resolves `TenantID` and `Resource` from the transaction context and returns a ca
622
622
623
623
| Key | Type | Resolution | Description |
624
624
|-----|------|------------|-------------|
625
-
| `"TenantID"` | `string` | `tx.Data` override → [`KeyResolver`](#keyresolver) → error | Azure AD tenant (e.g., `"contoso.onmicrosoft.com"`). If present in `tx.Data`, that value is used (connector override). If absent, the configured `KeyResolver` is called. If no resolver is configured, returns [`ErrMissingContextData`](#sentinel-errors). Malformed overrides (wrong type, empty) return [`ErrInvalidContextData`](#sentinel-errors) and never fall through to the resolver. The resolved value must match `^[a-zA-Z0-9][a-zA-Z0-9.\-]*$` regardless of source. |
626
-
| `"Resource"` | `string` | `tx.Data` only | Target resource (e.g., `"https://graph.microsoft.com"`). Always required in `tx.Data` — no resolver fallback. This is a per-request concern (which API the connector is calling). Returns [`ErrMissingContextData`](#sentinel-errors) if absent, [`ErrInvalidContextData`](#sentinel-errors) if not a string or empty. |
625
+
| `"TenantID"` | `string` | `tx.Data` override → [`KeyResolver`](#keyresolver) → error | Azure AD tenant (e.g., `"contoso.onmicrosoft.com"`). Implemented via `ResolveCredentialKey`. If present in `tx.Data`, that value is used (connector override). If absent, the configured `KeyResolver` is called. If no resolver is configured, returns [`ErrMissingContextData`](#sentinel-errors). Malformed overrides (wrong type, empty) return [`ErrInvalidContextData`](#sentinel-errors) and never fall through to the resolver. The resolved value must match `^[a-zA-Z0-9][a-zA-Z0-9.\-]*$` regardless of source. |
626
+
| `"Resource"` | `string` | `tx.Data` only | Target resource (e.g., `"https://graph.microsoft.com"`). Implemented via `DataString` plus explicit missing-field handling in the provider. Always required in `tx.Data` — no resolver fallback. This is a per-request concern (which API the connector is calling). Returns [`ErrMissingContextData`](#sentinel-errors) if absent, [`ErrInvalidContextData`](#sentinel-errors) if not a string or empty. |
Returns the `tx.Data[field]` string value when present and valid.
188
+
189
+
**Return values:**
190
+
- `value`: the string when present and valid
191
+
- `ok`: `true` when the field is present, `false` when absent
192
+
- `err`: `ErrInvalidContextData` when present but wrong type or empty
193
+
194
+
**Behavior:**
195
+
196
+
1. If `tx.Data[field]` is present and is a valid non-empty string, returns `(value, true, nil)`.
197
+
2. If present but has the wrong type or is an empty string, returns `("", true, ErrInvalidContextData)`.
198
+
3. If absent, returns `("", false, nil)`.
199
+
200
+
Use this helper to validate optional/required fields while keeping "missing field" policy at the call site (see [DataString usage example](../tutorials/microsoft-sam-mux.md#handling-context-data)).
201
+
179
202
#### Header Mapping
180
203
181
204
These fields are extracted from headers using the configured prefix
@@ -258,7 +281,27 @@ type ResponseAction struct {
258
281
259
282
---
260
283
261
-
## Public API
284
+
## Errors
285
+
286
+
### `ErrInvalidContextData`
287
+
288
+
```go
289
+
varErrInvalidContextData = errors.New("invalid context data type")
290
+
```
291
+
292
+
Indicates a transaction context field is present but fails validation (wrong type or empty string).
293
+
Used by [`DataString`](#datastring) and other context validation functions.
294
+
295
+
Check with [`errors.Is`](https://pkg.go.dev/errors#Is):
296
+
297
+
```go
298
+
value, ok, err:= tx.DataString("TenantID")
299
+
if errors.Is(err, sdk.ErrInvalidContextData) {
300
+
// Field present but invalid (wrong type or empty)
301
+
}
302
+
```
303
+
304
+
---
262
305
263
306
The Core module (`github.com/cloudblue/chaperone`) provides the entry
Copy file name to clipboardExpand all lines: docs/tutorials/microsoft-sam-mux.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -211,6 +211,7 @@ The proxy handles the full auth lifecycle:
211
211
## Going further
212
212
213
213
-**Resolve TenantID automatically** — Instead of requiring `TenantID` in every request's context data, use a [`KeyResolver`](../reference/contrib-plugins.md#keyresolver) to map transaction fields (marketplace, vendor) to the correct tenant. The built-in [`StaticMapping`](../reference/contrib-plugins.md#staticmapping) provides a declarative rule table — see the [reference](../reference/contrib-plugins.md#staticmapping) for configuration details.
214
+
`TenantID` supports resolver fallback; `Resource` remains a required explicit value in `X-Connect-Context-Data` for each request.
214
215
215
216
-**Add more tenants** — Run `chaperone-onboard microsoft` for each tenant and place the token file in the `tokens/` directory. One onboarding per tenant (MRRT). The `RefreshTokenSource` manages an LRU pool of per-tenant entries automatically.
216
217
-**Multiple app registrations** — If different groups of tenants require separate Azure AD app registrations (e.g., one per region or partner program), create a `RefreshTokenSource` per app and route them through the Mux. Each source gets its own `KeyResolver` for tenant resolution. All sources can share a single `FileStore` because tokens are keyed by tenant, not by app registration. See the [multiple app registrations example](../reference/contrib-plugins.md#multiple-microsoft-app-registrations) in the contrib reference for complete code.
returnnil, fmt.Errorf("Resource not present in transaction context: %w", //nolint:staticcheck // Resource is an SDK context key identifier, so ignore ST1005 (capitalized error string)
0 commit comments