spaps 0.8.2__tar.gz → 0.8.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {spaps-0.8.2 → spaps-0.8.3}/.gitignore +2 -2
- {spaps-0.8.2 → spaps-0.8.3}/CHANGELOG.md +22 -1
- {spaps-0.8.2 → spaps-0.8.3}/PKG-INFO +68 -2
- {spaps-0.8.2 → spaps-0.8.3}/README.md +67 -1
- spaps-0.8.3/docs/account-security.md +61 -0
- {spaps-0.8.2 → spaps-0.8.3}/pyproject.toml +1 -1
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/__init__.py +101 -1
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/async_client.py +36 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/auth.py +910 -105
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/auth_async.py +720 -82
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/capability.py +8 -0
- spaps-0.8.3/src/spaps_client/cfo_actions.py +417 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/client.py +36 -0
- spaps-0.8.3/src/spaps_client/dashboard.py +545 -0
- spaps-0.8.3/src/spaps_client/dashboard_async.py +360 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/dev_portal.py +25 -5
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/dev_portal_async.py +7 -1
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/payments.py +26 -3
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/payments_async.py +21 -1
- spaps-0.8.3/src/spaps_client/purchase_journeys.py +541 -0
- spaps-0.8.3/src/spaps_client/purchase_journeys_async.py +131 -0
- spaps-0.8.3/src/spaps_client/storage.py +295 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/webhooks.py +1 -1
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/whitelist.py +63 -39
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/whitelist_async.py +16 -36
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_async_client.py +1 -1
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_auth.py +1 -1
- spaps-0.8.3/tests/unit/test_auth_security_parity.py +495 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_capability.py +77 -0
- spaps-0.8.3/tests/unit/test_cfo_actions.py +171 -0
- spaps-0.8.3/tests/unit/test_dashboard.py +221 -0
- spaps-0.8.3/tests/unit/test_dashboard_authentication.py +167 -0
- spaps-0.8.3/tests/unit/test_dashboard_billing.py +64 -0
- spaps-0.8.3/tests/unit/test_dashboard_communications.py +39 -0
- spaps-0.8.3/tests/unit/test_dashboard_entitlement_options.py +38 -0
- spaps-0.8.3/tests/unit/test_dashboard_management_routes.py +58 -0
- spaps-0.8.3/tests/unit/test_dashboard_onboarding.py +312 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_dev_portal.py +99 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_dev_portal_async.py +73 -1
- spaps-0.8.3/tests/unit/test_metadata.py +67 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_passkey_parity.py +34 -17
- spaps-0.8.3/tests/unit/test_prepared_checkout.py +99 -0
- spaps-0.8.3/tests/unit/test_purchase_journeys.py +442 -0
- spaps-0.8.3/tests/unit/test_session_context_capabilities.py +40 -0
- spaps-0.8.3/tests/unit/test_staged_passkey_bootstrap.py +365 -0
- spaps-0.8.3/tests/unit/test_storage.py +373 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_webhooks.py +20 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_whitelist.py +211 -2
- spaps-0.8.2/src/spaps_client/storage.py +0 -199
- spaps-0.8.2/tests/unit/test_metadata.py +0 -32
- spaps-0.8.2/tests/unit/test_storage.py +0 -166
- {spaps-0.8.2 → spaps-0.8.3}/FULL_CHECKLIST.md +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/LICENSE +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/TDD_PLAN.md +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/TODO.md +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/docs/RELEASE_CHECKLIST.md +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/scripts/manage_version.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/app_links.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/app_links_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/cfo.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/cfo_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/cfo_browser_session.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/config.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/crypto.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/crypto_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/dayrate.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/dayrate_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/developer_projects.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/device_flow.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/email.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/email_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/entitlements.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/entitlements_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/http.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/http_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/issue_reporting.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/issue_reporting_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/marketing.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/metrics.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/metrics_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/permissions.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/py.typed +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/secure_messages.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/secure_messages_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/sessions.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/sessions_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/skill_evals.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/skill_evals_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/support_telemetry.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/token_gates.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/token_gates_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/usage.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/usage_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/users.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/users_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/x402.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/src/spaps_client/x402_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/conftest.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/integration/test_build.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/integration/test_smoke.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_app_links.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_auth_methods_origin.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_auth_sessions.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_cfo.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_cfo_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_cfo_browser_session.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_client.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_config.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_crypto_invoice_flags.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_dayrate.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_developer_projects.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_device_flow.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_email.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_entitlements.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_http.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_issue_reporting.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_marketing.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_metrics.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_payments.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_permissions.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_quickstart_full_adoption_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_readme_snippets.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_recovery_landing_profile.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_recovery_mfa.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_secure_messages.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_sessions.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_skill_evals.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_support_telemetry.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_token_gates.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_token_gates_docs_snippets.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_usage.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_users.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_users_async.py +0 -0
- {spaps-0.8.2 → spaps-0.8.3}/tests/unit/test_x402.py +0 -0
|
@@ -8,9 +8,30 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
|
|
|
8
8
|
|
|
9
9
|
- No changes yet.
|
|
10
10
|
|
|
11
|
+
## [0.8.3] - 2026-10-24
|
|
12
|
+
|
|
13
|
+
**Unpublished source candidate.** This date records candidate preparation, not
|
|
14
|
+
registry publication or downstream deployment.
|
|
15
|
+
|
|
16
|
+
- Prepare the `0.8.3.dev0` checkout as `0.8.3` alongside server `0.9.1`
|
|
17
|
+
([54a0059a](https://github.com/build000r/sweet-potato/commit/54a0059aba568f750da284496c4863a0db695cf4)).
|
|
18
|
+
- Include sync/async purchase-journey and developer-portal helpers, scoped
|
|
19
|
+
dashboard controls, capability decisions, and authenticated CFO action-journey
|
|
20
|
+
helpers added since the retained public `0.8.2` baseline.
|
|
21
|
+
|
|
22
|
+
## [0.8.3.dev0] - 2026-10-22
|
|
23
|
+
|
|
24
|
+
**Unpublished development checkout.**
|
|
25
|
+
|
|
26
|
+
- Separate the expanded checkout API from the public `0.8.2` artifact observed
|
|
27
|
+
on 2026-10-22. The offline surface guard rejects different APIs using the same
|
|
28
|
+
version and validates retained artifact provenance before comparing them.
|
|
29
|
+
|
|
11
30
|
## [0.8.2] - 2026-10-01
|
|
12
31
|
|
|
13
|
-
**
|
|
32
|
+
**Public artifact observed 2026-10-22.** This heading originally described a
|
|
33
|
+
source candidate. Registry observation does not establish its publication date.
|
|
34
|
+
The original candidate superseded tagged but unpublished `0.8.1`.
|
|
14
35
|
|
|
15
36
|
- Repack the reviewed source cohort with corrected exact-artifact inspection; no Python client API change.
|
|
16
37
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: spaps
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
4
4
|
Summary: Python client for the hosted Sweet Potato / SPAPS API
|
|
5
5
|
Project-URL: Homepage, https://sweetpotato.dev
|
|
6
6
|
Project-URL: Documentation, https://docs.sweetpotato.dev
|
|
@@ -214,6 +214,28 @@ credential = client.auth.webauthn_register_verify(
|
|
|
214
214
|
|
|
215
215
|
The sync and async auth clients also cover passkey-first bootstrap, credential listing/labeling/revocation, application passkey profiles, action-bound step-up, user recovery, and administrator recovery preparation/execution. Pass `origin` on ceremonies so SPAPS can validate the browser origin. Public ceremonies send only `X-API-Key`; lifecycle, profile, step-up, and administrator operations also require a bearer token, using an explicit `access_token` before stored credentials.
|
|
216
216
|
|
|
217
|
+
Passkey signup's `webauthn_bootstrap_verify` returns a restricted
|
|
218
|
+
`WebAuthnBootstrapPendingResponse`, without account/session creation or token
|
|
219
|
+
storage. Keep its `bootstrap_grant` in attempt memory, obtain a fresh assertion
|
|
220
|
+
from the user's authenticator, then submit that grant, `challenge_id`, and
|
|
221
|
+
credential through `webauthn_bootstrap_assertion_verify`. Only the validated final
|
|
222
|
+
response stores tokens. Preserve the original application, Origin/RP, user
|
|
223
|
+
handle, and expiry; discard the grant when the attempt ends. Ordinary membership
|
|
224
|
+
does not confer a dashboard grant.
|
|
225
|
+
|
|
226
|
+
Bootstrap also binds configuration identity/version and the security profile
|
|
227
|
+
fingerprint across both ceremonies; security profile changes require fresh
|
|
228
|
+
options, while cosmetic display-name changes remain valid. Signup requests a
|
|
229
|
+
discoverable passkey with `resident_key="required"`; authenticated enrollment
|
|
230
|
+
keeps its configured preference. This changed contract in checkout Python
|
|
231
|
+
`0.8.3` requires coordinated server and matching SDK/types/Python package/channel
|
|
232
|
+
adoption, including the server/keyscope stored-rule contract. Publishable final
|
|
233
|
+
assertion needs an exact singleton POST rule in
|
|
234
|
+
`publishable_key_access.allowed_routes`; declared scopes, legacy defaults, and
|
|
235
|
+
pattern backfill cannot enable it. Compiled browser/dashboard settings contain
|
|
236
|
+
the rule; custom/legacy settings need an explicit adoption upgrade. Checkout
|
|
237
|
+
source does not prove published or deployed compatibility.
|
|
238
|
+
|
|
217
239
|
Python coordinates the server half of each WebAuthn ceremony. It returns typed registration or assertion options and accepts the credential JSON produced by a browser or another WebAuthn-capable user agent. It does not call `navigator.credentials`, emulate an authenticator, perform CTAP, or sign challenges. Recovery registration rotates the recovery grant; it does not issue login tokens until the new credential completes the recovery assertion.
|
|
218
240
|
|
|
219
241
|
## Core Surface
|
|
@@ -853,6 +875,9 @@ payload = verify_spaps_webhook(
|
|
|
853
875
|
print(payload.type)
|
|
854
876
|
```
|
|
855
877
|
|
|
878
|
+
The default five-minute verification window allows bounded clock skew in either
|
|
879
|
+
direction. Timestamps farther in the future or past are rejected.
|
|
880
|
+
|
|
856
881
|
## Validation
|
|
857
882
|
|
|
858
883
|
From the repository root:
|
|
@@ -920,6 +945,8 @@ The default is `InMemoryTokenStorage`. For persistence, pass
|
|
|
920
945
|
`FileTokenStorage(path=...)`: it replaces the token file only after a complete
|
|
921
946
|
write, keeps file permissions owner-only on POSIX, and rejects symlinked storage
|
|
922
947
|
directories. Loading ignores symlinked or malformed token files.
|
|
948
|
+
On platforms without directory-relative no-follow I/O, symlink checks are
|
|
949
|
+
best-effort; use a private storage path with trusted ancestors.
|
|
923
950
|
|
|
924
951
|
### Does it retry requests automatically?
|
|
925
952
|
|
|
@@ -927,11 +954,17 @@ It can. Pass `RetryConfig` if you want retry and backoff behavior.
|
|
|
927
954
|
|
|
928
955
|
## Metadata
|
|
929
956
|
|
|
957
|
+
This checkout is the unpublished `0.8.3` source candidate. It includes APIs beyond
|
|
958
|
+
the retained public `0.8.2` artifact and has no publication receipt. After publishing a version,
|
|
959
|
+
advance the checkout to its next development version before changing its API.
|
|
960
|
+
The offline package-surface check compares checkout declarations with retained
|
|
961
|
+
public artifacts; release and consumer adoption still require their own receipts.
|
|
962
|
+
|
|
930
963
|
The metadata below describes this checkout. `latest_version` is the source
|
|
931
964
|
package version; it does not establish registry publication or availability.
|
|
932
965
|
|
|
933
966
|
- `package_name`: `spaps`
|
|
934
|
-
- `latest_version`: `0.8.
|
|
967
|
+
- `latest_version`: `0.8.3`
|
|
935
968
|
- `minimum_runtime`: `Python >=3.9`
|
|
936
969
|
- `api_base_url`: `https://api.sweetpotato.dev`
|
|
937
970
|
|
|
@@ -983,3 +1016,36 @@ The bridge constructor requires `spaps_origin`, allowed application `origin`, br
|
|
|
983
1016
|
`response_handler(status, cookies, location)` receives ordered raw allowlisted `Set-Cookie` values, including deletions and failure responses. It must apply them at the actual SPAPS browser origin before forwarding an optional validated Intuit navigation. A BFF on an unrelated hostname cannot set SPAPS host-only cookies. The callback URLs and cookies are sensitive trusted bridge inputs: do not serialize them into ordinary application results or logs. A local cookie sink does not provision this deployed bridge.
|
|
984
1017
|
|
|
985
1018
|
On refresh-cookie rotation, `invalidate_access` must invalidate the cached bearer. Before another deliberate call, the host must reacquire current access through shared SPAPS auth, apply any further cookie updates, and expose that new bearer. Neither adapter refreshes or replays the operation. `CfoError` exposes only bounded `code`, `status`, and optional `request_id`; it does not retain the raw HTTP error. Deployment still requires the real origin/CSRF/cookie bridge, safe host logging, external CFO executor adoption, and the human retirement gate. These checkout APIs do not establish published package availability.
|
|
1019
|
+
# Dashboard (checkout)
|
|
1020
|
+
|
|
1021
|
+
`client.dashboard` provides `context()`, `list_applications()`,
|
|
1022
|
+
`get_application(id)`, `list_records(kind, **filters)`, and `get_record(kind, id)`.
|
|
1023
|
+
`AsyncDashboardClient` has matching asynchronous reads. Each read requires an
|
|
1024
|
+
application credential and a current user session. Results contain stored
|
|
1025
|
+
records for owned applications, or global-admin scope, with pagination and
|
|
1026
|
+
source freshness. Retained email content is detail-only; authentication content
|
|
1027
|
+
is restricted. See [dashboard reads](https://github.com/build000r/sweet-potato/blob/main/docs/api/dashboard.md).
|
|
1028
|
+
Application dictionaries preserve `entitlement_options` for configured keys,
|
|
1029
|
+
sources and enabled flags, independently of `overview.stored_grants`. Missing/null
|
|
1030
|
+
catalog data from older servers is unavailable, not an empty catalog.
|
|
1031
|
+
Use `list_records('email-templates')` for template definitions and
|
|
1032
|
+
`list_records('email-logs')` for individual sends. Sync and async dictionaries
|
|
1033
|
+
preserve definition name/key, enabled state, stream, category and dates.
|
|
1034
|
+
Package publication and production deployment require separate evidence.
|
|
1035
|
+
|
|
1036
|
+
For the dedicated operator console, the sync and async clients also expose
|
|
1037
|
+
`management_options(application_id)`, `invite`, `send_recovery`, `grant`, `revoke`,
|
|
1038
|
+
`create_entitlement_option`, and `create_application`. These require the console application's session and
|
|
1039
|
+
Viewer/Support/Admin entitlement checks; Viewer cannot write. Support handles
|
|
1040
|
+
approved ordinary app access, while Admin also manages console access and creates
|
|
1041
|
+
applications. See [console roles and setup](https://github.com/build000r/sweet-potato/blob/main/docs/guides/dashboard-access.md).
|
|
1042
|
+
Application option creation requires exact-app Admin authority and adds a manual
|
|
1043
|
+
key without granting user access. Existing console applications need the new exact
|
|
1044
|
+
POST route opt-in; checkout source does not establish production availability.
|
|
1045
|
+
|
|
1046
|
+
Application Billing uses `billing_workspace(application_id)` and
|
|
1047
|
+
`billing_action(operation, application_id=..., expected_revision=..., data=...)`
|
|
1048
|
+
in both clients. Actions use a fixed operation list and retain the caller's
|
|
1049
|
+
session; the server rechecks target-app authority. Account attachment requires
|
|
1050
|
+
portfolio Admin. An ambiguous provider failure is not retried automatically.
|
|
1051
|
+
See [Billing configuration](https://github.com/build000r/sweet-potato/blob/main/docs/demos/spaps-dashboard/BILLING.md).
|
|
@@ -146,6 +146,28 @@ credential = client.auth.webauthn_register_verify(
|
|
|
146
146
|
|
|
147
147
|
The sync and async auth clients also cover passkey-first bootstrap, credential listing/labeling/revocation, application passkey profiles, action-bound step-up, user recovery, and administrator recovery preparation/execution. Pass `origin` on ceremonies so SPAPS can validate the browser origin. Public ceremonies send only `X-API-Key`; lifecycle, profile, step-up, and administrator operations also require a bearer token, using an explicit `access_token` before stored credentials.
|
|
148
148
|
|
|
149
|
+
Passkey signup's `webauthn_bootstrap_verify` returns a restricted
|
|
150
|
+
`WebAuthnBootstrapPendingResponse`, without account/session creation or token
|
|
151
|
+
storage. Keep its `bootstrap_grant` in attempt memory, obtain a fresh assertion
|
|
152
|
+
from the user's authenticator, then submit that grant, `challenge_id`, and
|
|
153
|
+
credential through `webauthn_bootstrap_assertion_verify`. Only the validated final
|
|
154
|
+
response stores tokens. Preserve the original application, Origin/RP, user
|
|
155
|
+
handle, and expiry; discard the grant when the attempt ends. Ordinary membership
|
|
156
|
+
does not confer a dashboard grant.
|
|
157
|
+
|
|
158
|
+
Bootstrap also binds configuration identity/version and the security profile
|
|
159
|
+
fingerprint across both ceremonies; security profile changes require fresh
|
|
160
|
+
options, while cosmetic display-name changes remain valid. Signup requests a
|
|
161
|
+
discoverable passkey with `resident_key="required"`; authenticated enrollment
|
|
162
|
+
keeps its configured preference. This changed contract in checkout Python
|
|
163
|
+
`0.8.3` requires coordinated server and matching SDK/types/Python package/channel
|
|
164
|
+
adoption, including the server/keyscope stored-rule contract. Publishable final
|
|
165
|
+
assertion needs an exact singleton POST rule in
|
|
166
|
+
`publishable_key_access.allowed_routes`; declared scopes, legacy defaults, and
|
|
167
|
+
pattern backfill cannot enable it. Compiled browser/dashboard settings contain
|
|
168
|
+
the rule; custom/legacy settings need an explicit adoption upgrade. Checkout
|
|
169
|
+
source does not prove published or deployed compatibility.
|
|
170
|
+
|
|
149
171
|
Python coordinates the server half of each WebAuthn ceremony. It returns typed registration or assertion options and accepts the credential JSON produced by a browser or another WebAuthn-capable user agent. It does not call `navigator.credentials`, emulate an authenticator, perform CTAP, or sign challenges. Recovery registration rotates the recovery grant; it does not issue login tokens until the new credential completes the recovery assertion.
|
|
150
172
|
|
|
151
173
|
## Core Surface
|
|
@@ -785,6 +807,9 @@ payload = verify_spaps_webhook(
|
|
|
785
807
|
print(payload.type)
|
|
786
808
|
```
|
|
787
809
|
|
|
810
|
+
The default five-minute verification window allows bounded clock skew in either
|
|
811
|
+
direction. Timestamps farther in the future or past are rejected.
|
|
812
|
+
|
|
788
813
|
## Validation
|
|
789
814
|
|
|
790
815
|
From the repository root:
|
|
@@ -852,6 +877,8 @@ The default is `InMemoryTokenStorage`. For persistence, pass
|
|
|
852
877
|
`FileTokenStorage(path=...)`: it replaces the token file only after a complete
|
|
853
878
|
write, keeps file permissions owner-only on POSIX, and rejects symlinked storage
|
|
854
879
|
directories. Loading ignores symlinked or malformed token files.
|
|
880
|
+
On platforms without directory-relative no-follow I/O, symlink checks are
|
|
881
|
+
best-effort; use a private storage path with trusted ancestors.
|
|
855
882
|
|
|
856
883
|
### Does it retry requests automatically?
|
|
857
884
|
|
|
@@ -859,11 +886,17 @@ It can. Pass `RetryConfig` if you want retry and backoff behavior.
|
|
|
859
886
|
|
|
860
887
|
## Metadata
|
|
861
888
|
|
|
889
|
+
This checkout is the unpublished `0.8.3` source candidate. It includes APIs beyond
|
|
890
|
+
the retained public `0.8.2` artifact and has no publication receipt. After publishing a version,
|
|
891
|
+
advance the checkout to its next development version before changing its API.
|
|
892
|
+
The offline package-surface check compares checkout declarations with retained
|
|
893
|
+
public artifacts; release and consumer adoption still require their own receipts.
|
|
894
|
+
|
|
862
895
|
The metadata below describes this checkout. `latest_version` is the source
|
|
863
896
|
package version; it does not establish registry publication or availability.
|
|
864
897
|
|
|
865
898
|
- `package_name`: `spaps`
|
|
866
|
-
- `latest_version`: `0.8.
|
|
899
|
+
- `latest_version`: `0.8.3`
|
|
867
900
|
- `minimum_runtime`: `Python >=3.9`
|
|
868
901
|
- `api_base_url`: `https://api.sweetpotato.dev`
|
|
869
902
|
|
|
@@ -915,3 +948,36 @@ The bridge constructor requires `spaps_origin`, allowed application `origin`, br
|
|
|
915
948
|
`response_handler(status, cookies, location)` receives ordered raw allowlisted `Set-Cookie` values, including deletions and failure responses. It must apply them at the actual SPAPS browser origin before forwarding an optional validated Intuit navigation. A BFF on an unrelated hostname cannot set SPAPS host-only cookies. The callback URLs and cookies are sensitive trusted bridge inputs: do not serialize them into ordinary application results or logs. A local cookie sink does not provision this deployed bridge.
|
|
916
949
|
|
|
917
950
|
On refresh-cookie rotation, `invalidate_access` must invalidate the cached bearer. Before another deliberate call, the host must reacquire current access through shared SPAPS auth, apply any further cookie updates, and expose that new bearer. Neither adapter refreshes or replays the operation. `CfoError` exposes only bounded `code`, `status`, and optional `request_id`; it does not retain the raw HTTP error. Deployment still requires the real origin/CSRF/cookie bridge, safe host logging, external CFO executor adoption, and the human retirement gate. These checkout APIs do not establish published package availability.
|
|
951
|
+
# Dashboard (checkout)
|
|
952
|
+
|
|
953
|
+
`client.dashboard` provides `context()`, `list_applications()`,
|
|
954
|
+
`get_application(id)`, `list_records(kind, **filters)`, and `get_record(kind, id)`.
|
|
955
|
+
`AsyncDashboardClient` has matching asynchronous reads. Each read requires an
|
|
956
|
+
application credential and a current user session. Results contain stored
|
|
957
|
+
records for owned applications, or global-admin scope, with pagination and
|
|
958
|
+
source freshness. Retained email content is detail-only; authentication content
|
|
959
|
+
is restricted. See [dashboard reads](https://github.com/build000r/sweet-potato/blob/main/docs/api/dashboard.md).
|
|
960
|
+
Application dictionaries preserve `entitlement_options` for configured keys,
|
|
961
|
+
sources and enabled flags, independently of `overview.stored_grants`. Missing/null
|
|
962
|
+
catalog data from older servers is unavailable, not an empty catalog.
|
|
963
|
+
Use `list_records('email-templates')` for template definitions and
|
|
964
|
+
`list_records('email-logs')` for individual sends. Sync and async dictionaries
|
|
965
|
+
preserve definition name/key, enabled state, stream, category and dates.
|
|
966
|
+
Package publication and production deployment require separate evidence.
|
|
967
|
+
|
|
968
|
+
For the dedicated operator console, the sync and async clients also expose
|
|
969
|
+
`management_options(application_id)`, `invite`, `send_recovery`, `grant`, `revoke`,
|
|
970
|
+
`create_entitlement_option`, and `create_application`. These require the console application's session and
|
|
971
|
+
Viewer/Support/Admin entitlement checks; Viewer cannot write. Support handles
|
|
972
|
+
approved ordinary app access, while Admin also manages console access and creates
|
|
973
|
+
applications. See [console roles and setup](https://github.com/build000r/sweet-potato/blob/main/docs/guides/dashboard-access.md).
|
|
974
|
+
Application option creation requires exact-app Admin authority and adds a manual
|
|
975
|
+
key without granting user access. Existing console applications need the new exact
|
|
976
|
+
POST route opt-in; checkout source does not establish production availability.
|
|
977
|
+
|
|
978
|
+
Application Billing uses `billing_workspace(application_id)` and
|
|
979
|
+
`billing_action(operation, application_id=..., expected_revision=..., data=...)`
|
|
980
|
+
in both clients. Actions use a fixed operation list and retain the caller's
|
|
981
|
+
session; the server rechecks target-app authority. Account attachment requires
|
|
982
|
+
portfolio Admin. An ambiguous provider failure is not retried automatically.
|
|
983
|
+
See [Billing configuration](https://github.com/build000r/sweet-potato/blob/main/docs/demos/spaps-dashboard/BILLING.md).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Account security and human GitHub OAuth
|
|
2
|
+
|
|
3
|
+
`client.auth` exposes the same canonical account-security endpoints as the
|
|
4
|
+
TypeScript SDK. `AsyncSpapsClient` exposes the same method names and arguments;
|
|
5
|
+
await each call. Result models are exported from `spaps_client.auth`.
|
|
6
|
+
|
|
7
|
+
| Python method | Canonical path under `/api/auth` |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `get_security_summary()` | `GET /security` |
|
|
10
|
+
| `security_wallet_challenge(wallet_address=..., chain_type=...)` | `POST /security/wallets/challenge` |
|
|
11
|
+
| `security_wallet_link(...)` | `POST /security/wallets/link` |
|
|
12
|
+
| `security_wallet_remove(record_id=...)` | `DELETE /security/wallets/{id}` |
|
|
13
|
+
| `security_provider_nonce(provider=..., client_type=..., redirect_uri=...)` | `POST /security/providers/nonce` |
|
|
14
|
+
| `security_provider_link(...)` | `POST /security/providers/link` |
|
|
15
|
+
| `security_provider_remove(record_id=...)` | `DELETE /security/providers/{id}` |
|
|
16
|
+
| `security_phone_request(phone_number=...)` | `POST /security/phone/request` |
|
|
17
|
+
| `security_phone_verify(phone_number=..., code=..., challenge_id=...)` | `POST /security/phone/verify` |
|
|
18
|
+
| `security_phone_remove()` | `DELETE /security/phone` |
|
|
19
|
+
| `security_email_request(email=...)` | `POST /security/email/request` |
|
|
20
|
+
| `security_email_verify(email=..., code=..., challenge_id=...)` | `POST /security/email/verify` |
|
|
21
|
+
| `github_start(redirect_url=...)` / `github_complete(code=..., state=...)` | `POST /github/start` and `/github/complete` |
|
|
22
|
+
| `security_github_start(redirect_url=...)` / `security_github_complete(code=..., state=...)` | `POST /security/github/start` and `/security/github/complete` |
|
|
23
|
+
| `sign_up(email=..., password=...)` | `POST /signup` |
|
|
24
|
+
| `request_signup_confirmation(email=..., redirect_url=...)` | `POST /signup/confirmation/request` |
|
|
25
|
+
| `verify_signup_confirmation(token=...)` | `POST /signup/confirmation/verify` |
|
|
26
|
+
|
|
27
|
+
Security methods require the current access token, supplied through token
|
|
28
|
+
storage or `access_token=...`. All methods above accept `origin=...`; send the
|
|
29
|
+
registered application origin where server policy requires it. They retain the
|
|
30
|
+
application API key and use the configured HTTP client's cookie jar.
|
|
31
|
+
|
|
32
|
+
Linking returns `AuthLinkResult`, never a replacement login session. If a
|
|
33
|
+
successful change reports `session_ended=True`, the client clears stored
|
|
34
|
+
credentials. Removal returns `AuthRemoveResult`; the server decides whether an
|
|
35
|
+
alternative sign-in method remains viable. There is no email-removal endpoint.
|
|
36
|
+
Delivery status may describe a console simulation; it does not prove SMS arrived.
|
|
37
|
+
|
|
38
|
+
Human GitHub uses `oauth:github`, separate from machine `oidc:github`. The start
|
|
39
|
+
and completion calls require the same app/origin/browser binding. A Python HTTP
|
|
40
|
+
client cannot transfer an HttpOnly browser cookie across clients automatically.
|
|
41
|
+
Browser integrations should use the shared browser SDK popup helper, retaining
|
|
42
|
+
the current bearer session for account linking. Do not retry a failed link as a
|
|
43
|
+
sign-in operation. Provider access tokens are never client results.
|
|
44
|
+
|
|
45
|
+
`sign_up` returns `SignupPending`, `MfaRequiredChallenge`, or `TokenPair`.
|
|
46
|
+
Pending confirmation and MFA challenges do not replace stored credentials.
|
|
47
|
+
`verify_signup_confirmation` returns a restricted `password_setup_token`; it
|
|
48
|
+
does not authenticate or store that grant as an access token. Continue through
|
|
49
|
+
the existing password setup and normal sign-in flow.
|
|
50
|
+
|
|
51
|
+
Both clients accept `origin=...` on `oidc_nonce` and `oidc_sign_in`. For Apple
|
|
52
|
+
browser calls, pass the same exact configured origin on nonce and completion;
|
|
53
|
+
the client forwards it as the request's `Origin` header. A redirect URI does not
|
|
54
|
+
set that header. The server rejects a missing or mismatched browser origin.
|
|
55
|
+
|
|
56
|
+
Apple OIDC methods support `client_type` and `redirect_uri`; completion also
|
|
57
|
+
accepts `authorization_code`. Omit those Apple profile fields for Google.
|
|
58
|
+
Native Apple calls keep their existing profile without requiring browser Origin.
|
|
59
|
+
Wallet
|
|
60
|
+
`request_nonce(..., chain="base")` preserves its existing Python argument name
|
|
61
|
+
and sends the server's canonical `chain_type` field.
|
|
@@ -7,6 +7,14 @@ payments, and supporting utilities as implementation progresses.
|
|
|
7
7
|
|
|
8
8
|
from .cfo import CfoClient, CfoDecision, CfoDecisionRequest, CfoError, CfoStartRequest
|
|
9
9
|
from .cfo_async import AsyncCfoClient
|
|
10
|
+
from .cfo_actions import (
|
|
11
|
+
CfoActionsClient, AsyncCfoActionsClient, CfoActionVerifier, AsyncCfoActionVerifier,
|
|
12
|
+
CfoActionBrowserSession, AsyncCfoActionBrowserSession,
|
|
13
|
+
Invitation as CfoActionInvitation, Delivery as CfoActionDelivery,
|
|
14
|
+
Status as CfoActionStatus, Claim as CfoActionClaim,
|
|
15
|
+
VerificationBinding as CfoActionVerificationBinding,
|
|
16
|
+
RuntimeEnvelope as CfoActionRuntimeEnvelope,
|
|
17
|
+
)
|
|
10
18
|
from .cfo_browser_session import CfoBrowserCredentials, CfoBrowserSession, AsyncCfoBrowserSession
|
|
11
19
|
from .auth import (
|
|
12
20
|
AuthClient,
|
|
@@ -33,6 +41,7 @@ from .auth import (
|
|
|
33
41
|
WebAuthnAssertionOptionsResponse,
|
|
34
42
|
WebAuthnRegisterVerifyResponse,
|
|
35
43
|
WebAuthnBootstrapVerifyResponse,
|
|
44
|
+
WebAuthnBootstrapPendingResponse,
|
|
36
45
|
WebAuthnCredentialDescriptor,
|
|
37
46
|
PasskeyTransport,
|
|
38
47
|
WebAuthnRelyingParty,
|
|
@@ -76,12 +85,20 @@ from .payments import (
|
|
|
76
85
|
PaymentsClient,
|
|
77
86
|
PaymentsError,
|
|
78
87
|
CheckoutSession,
|
|
88
|
+
CheckoutSessionDetails,
|
|
89
|
+
CheckoutSessionSummary,
|
|
90
|
+
CheckoutSessionList,
|
|
91
|
+
ExpireCheckoutSessionResult,
|
|
79
92
|
PaymentIntent,
|
|
80
93
|
WalletDeposit,
|
|
81
94
|
WalletTransaction,
|
|
82
95
|
SubscriptionPlan,
|
|
96
|
+
SubscriptionItemPriceRecurring,
|
|
97
|
+
SubscriptionItemPrice,
|
|
98
|
+
SubscriptionItem,
|
|
83
99
|
SubscriptionDetail,
|
|
84
100
|
SubscriptionCancellation,
|
|
101
|
+
SubscriptionList,
|
|
85
102
|
BalanceOverview,
|
|
86
103
|
BalanceAmounts,
|
|
87
104
|
UsageSummary,
|
|
@@ -89,6 +106,12 @@ from .payments import (
|
|
|
89
106
|
ProductPrice,
|
|
90
107
|
Product,
|
|
91
108
|
ProductList,
|
|
109
|
+
GuestCheckoutSession,
|
|
110
|
+
GuestCheckoutSessionSummary,
|
|
111
|
+
GuestCheckoutSessionList,
|
|
112
|
+
GuestCheckoutConversionResult,
|
|
113
|
+
PaymentRecord,
|
|
114
|
+
PaymentHistory,
|
|
92
115
|
)
|
|
93
116
|
from .whitelist import (
|
|
94
117
|
WhitelistClient,
|
|
@@ -185,9 +208,12 @@ from .developer_projects import (
|
|
|
185
208
|
ResetProjectPairResponse,
|
|
186
209
|
RotateEnvironmentKeyResponse,
|
|
187
210
|
)
|
|
211
|
+
from .dashboard import DashboardClient, DashboardDetail, DashboardKind, DashboardPage, DashboardSource
|
|
212
|
+
from .dashboard_async import AsyncDashboardClient
|
|
188
213
|
from .dev_portal import (
|
|
189
214
|
DEV_PORTAL_HELPERS,
|
|
190
215
|
DeleteApplicationResponse,
|
|
216
|
+
DevPortalCheckoutSessionResponse,
|
|
191
217
|
DevPortalClient,
|
|
192
218
|
DevPortalError,
|
|
193
219
|
ListOwnedApplicationsResponse,
|
|
@@ -370,7 +396,66 @@ from .storage import (
|
|
|
370
396
|
)
|
|
371
397
|
from .http import RetryConfig, LoggingHooks, default_logging_hooks
|
|
372
398
|
|
|
399
|
+
from .purchase_journeys import (
|
|
400
|
+
SubmittedJourneyIdentity,
|
|
401
|
+
CanonicalJourneyIdentity,
|
|
402
|
+
PreparedConsent,
|
|
403
|
+
ReceiptPaymentView,
|
|
404
|
+
ReceiptAccessView,
|
|
405
|
+
ReceiptIdentityView,
|
|
406
|
+
ConsumerSupportRequest,
|
|
407
|
+
ConsumerSupportResponse,
|
|
408
|
+
OnboardingVersion,
|
|
409
|
+
OnboardingFlow,
|
|
410
|
+
OnboardingFlowMutation,
|
|
411
|
+
ApproveOnboardingFlowRequest,
|
|
412
|
+
WithdrawOnboardingApprovalRequest,
|
|
413
|
+
RegisterJourneyPolicyRequest,
|
|
414
|
+
JourneyPolicyResponse,
|
|
415
|
+
AcceptJourneyConsentRequest,
|
|
416
|
+
JourneyConsentResponse,
|
|
417
|
+
PrepareJourneyRequest,
|
|
418
|
+
PreparedJourneyResponse,
|
|
419
|
+
ResumeJourneyRequest,
|
|
420
|
+
ResumeJourneyResponse,
|
|
421
|
+
ProvisioningInputRequest,
|
|
422
|
+
ProvisioningInputResponse,
|
|
423
|
+
IssueReceiptCapabilityRequest,
|
|
424
|
+
IssuedReceiptCapabilityResponse,
|
|
425
|
+
ReceiptStatusRequest,
|
|
426
|
+
ReceiptStatusResponse,
|
|
427
|
+
IssueAccessChallengeRequest,
|
|
428
|
+
IssuedAccessChallengeResponse,
|
|
429
|
+
VerifyAccessChallengeRequest,
|
|
430
|
+
VerifyAccessChallengeResponse,
|
|
431
|
+
AppProvisioningReportRequest,
|
|
432
|
+
AppProvisioningReportResponse,
|
|
433
|
+
PurchaseJourneysClient,
|
|
434
|
+
OnboardingDefinition,
|
|
435
|
+
OnboardingQuestion,
|
|
436
|
+
QuestionBase,
|
|
437
|
+
TextQuestion,
|
|
438
|
+
NumberQuestion,
|
|
439
|
+
BooleanQuestion,
|
|
440
|
+
ChoiceOption,
|
|
441
|
+
ChoiceQuestion,
|
|
442
|
+
FlowApproval,
|
|
443
|
+
)
|
|
444
|
+
from .purchase_journeys_async import AsyncPurchaseJourneysClient
|
|
445
|
+
from .dashboard import (
|
|
446
|
+
DashboardOnboardingWorkspace,
|
|
447
|
+
DashboardOnboardingJourneys,
|
|
448
|
+
DashboardOnboardingJourney,
|
|
449
|
+
DashboardOnboardingComparison,
|
|
450
|
+
OnboardingDraftWrite,
|
|
451
|
+
OnboardingPublishWrite,
|
|
452
|
+
OnboardingRollbackWrite,
|
|
453
|
+
OnboardingFlowWrite,
|
|
454
|
+
OnboardingCohort,
|
|
455
|
+
)
|
|
456
|
+
|
|
373
457
|
__all__ = [
|
|
458
|
+
"DashboardClient", "AsyncDashboardClient", "DashboardDetail", "DashboardKind", "DashboardPage", "DashboardSource",
|
|
374
459
|
"__version__",
|
|
375
460
|
"AuthClient",
|
|
376
461
|
"AuthMethodResult",
|
|
@@ -396,6 +481,7 @@ __all__ = [
|
|
|
396
481
|
"WebAuthnAssertionOptionsResponse",
|
|
397
482
|
"WebAuthnRegisterVerifyResponse",
|
|
398
483
|
"WebAuthnBootstrapVerifyResponse",
|
|
484
|
+
"WebAuthnBootstrapPendingResponse",
|
|
399
485
|
"WebAuthnCredentialDescriptor",
|
|
400
486
|
"PasskeyTransport",
|
|
401
487
|
"WebAuthnRelyingParty",
|
|
@@ -548,6 +634,7 @@ __all__ = [
|
|
|
548
634
|
"RotateEnvironmentKeyResponse",
|
|
549
635
|
"DEV_PORTAL_HELPERS",
|
|
550
636
|
"DeleteApplicationResponse",
|
|
637
|
+
"DevPortalCheckoutSessionResponse",
|
|
551
638
|
"DevPortalClient",
|
|
552
639
|
"DevPortalError",
|
|
553
640
|
"ListOwnedApplicationsResponse",
|
|
@@ -718,7 +805,20 @@ __all__ = [
|
|
|
718
805
|
]
|
|
719
806
|
|
|
720
807
|
# Temporary development version; replaced during release automation.
|
|
721
|
-
__version__ = "0.8.
|
|
808
|
+
__version__ = "0.8.3"
|
|
722
809
|
|
|
723
810
|
|
|
724
811
|
__all__ += ["CfoClient", "AsyncCfoClient", "CfoDecision", "CfoDecisionRequest", "CfoError", "CfoStartRequest", "CfoBrowserCredentials", "CfoBrowserSession", "AsyncCfoBrowserSession"]
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
__all__ += ['ConsumerSupportRequest', 'ConsumerSupportResponse', 'OnboardingVersion', 'OnboardingFlow', 'OnboardingFlowMutation', 'ApproveOnboardingFlowRequest', 'WithdrawOnboardingApprovalRequest', 'RegisterJourneyPolicyRequest', 'JourneyPolicyResponse', 'AcceptJourneyConsentRequest', 'JourneyConsentResponse', 'PrepareJourneyRequest', 'PreparedJourneyResponse', 'ResumeJourneyRequest', 'ResumeJourneyResponse', 'ProvisioningInputRequest', 'ProvisioningInputResponse', 'IssueReceiptCapabilityRequest', 'IssuedReceiptCapabilityResponse', 'ReceiptStatusRequest', 'ReceiptStatusResponse', 'IssueAccessChallengeRequest', 'IssuedAccessChallengeResponse', 'VerifyAccessChallengeRequest', 'VerifyAccessChallengeResponse', 'AppProvisioningReportRequest', 'AppProvisioningReportResponse', 'PurchaseJourneysClient', 'OnboardingDefinition', 'OnboardingQuestion', 'QuestionBase', 'TextQuestion', 'NumberQuestion', 'BooleanQuestion', 'ChoiceOption', 'ChoiceQuestion', 'FlowApproval', 'AsyncPurchaseJourneysClient']
|
|
815
|
+
|
|
816
|
+
__all__ += ['DashboardOnboardingWorkspace', 'DashboardOnboardingJourneys', 'DashboardOnboardingJourney', 'DashboardOnboardingComparison', 'OnboardingDraftWrite', 'OnboardingPublishWrite', 'OnboardingRollbackWrite', 'OnboardingFlowWrite', 'OnboardingCohort']
|
|
817
|
+
|
|
818
|
+
__all__ += ["SubmittedJourneyIdentity", "CanonicalJourneyIdentity", "PreparedConsent",
|
|
819
|
+
"ReceiptPaymentView", "ReceiptAccessView", "ReceiptIdentityView"]
|
|
820
|
+
|
|
821
|
+
__all__ += ["CfoActionsClient", "AsyncCfoActionsClient", "CfoActionVerifier", "AsyncCfoActionVerifier",
|
|
822
|
+
"CfoActionBrowserSession", "AsyncCfoActionBrowserSession", "CfoActionInvitation",
|
|
823
|
+
"CfoActionDelivery", "CfoActionStatus", "CfoActionClaim",
|
|
824
|
+
"CfoActionVerificationBinding", "CfoActionRuntimeEnvelope"]
|
|
@@ -7,6 +7,10 @@ from typing import Optional, TYPE_CHECKING
|
|
|
7
7
|
|
|
8
8
|
import httpx
|
|
9
9
|
|
|
10
|
+
from .cfo_actions import AsyncCfoActionsClient
|
|
11
|
+
from .purchase_journeys_async import AsyncPurchaseJourneysClient
|
|
12
|
+
from .dashboard_async import AsyncDashboardClient
|
|
13
|
+
|
|
10
14
|
from .cfo_async import AsyncCfoClient
|
|
11
15
|
|
|
12
16
|
from .app_links_async import AsyncAppLinksClient
|
|
@@ -79,6 +83,8 @@ class AsyncSpapsClient:
|
|
|
79
83
|
self._usage: Optional[AsyncUsageClient] = None
|
|
80
84
|
self._whitelist: Optional[AsyncWhitelistClient] = None
|
|
81
85
|
self._secure_messages: Optional[AsyncSecureMessagesClient] = None
|
|
86
|
+
self._purchase_journeys: Optional[AsyncPurchaseJourneysClient] = None
|
|
87
|
+
self._dashboard: Optional[AsyncDashboardClient] = None
|
|
82
88
|
self._dev_portal: Optional[AsyncDevPortalClient] = None
|
|
83
89
|
self._issue_reporting: Optional[AsyncIssueReportingClient] = None
|
|
84
90
|
self._metrics: Optional[AsyncMetricsClient] = None
|
|
@@ -92,6 +98,11 @@ class AsyncSpapsClient:
|
|
|
92
98
|
|
|
93
99
|
# Factories --------------------------------------------------------
|
|
94
100
|
|
|
101
|
+
@property
|
|
102
|
+
def cfo_actions(self) -> AsyncCfoActionsClient:
|
|
103
|
+
return AsyncCfoActionsClient(base_url=self.settings.base_url, api_key=self.settings.api_key,
|
|
104
|
+
access_token_provider=self._get_access_token_or_none)
|
|
105
|
+
|
|
95
106
|
@property
|
|
96
107
|
def cfo(self) -> AsyncCfoClient:
|
|
97
108
|
# Resolve the token at each operation, including on an already-held facade.
|
|
@@ -172,6 +183,29 @@ class AsyncSpapsClient:
|
|
|
172
183
|
self._secure_messages.access_token = access_token
|
|
173
184
|
return self._secure_messages
|
|
174
185
|
|
|
186
|
+
@property
|
|
187
|
+
def purchase_journeys(self) -> AsyncPurchaseJourneysClient:
|
|
188
|
+
"""Backend-only onboarding and receipt contracts; no human JWT required."""
|
|
189
|
+
if self._purchase_journeys is None:
|
|
190
|
+
self._purchase_journeys = AsyncPurchaseJourneysClient(
|
|
191
|
+
base_url=self.settings.base_url, api_key=self.settings.api_key,
|
|
192
|
+
client=self._client,
|
|
193
|
+
)
|
|
194
|
+
return self._purchase_journeys
|
|
195
|
+
|
|
196
|
+
@property
|
|
197
|
+
def dashboard(self) -> AsyncDashboardClient:
|
|
198
|
+
"""Stored application-owner and administrator dashboard records."""
|
|
199
|
+
access_token = self._require_access_token()
|
|
200
|
+
if self._dashboard is None:
|
|
201
|
+
self._dashboard = AsyncDashboardClient(
|
|
202
|
+
base_url=self.settings.base_url, api_key=self.settings.api_key,
|
|
203
|
+
access_token=access_token, client=self._client,
|
|
204
|
+
)
|
|
205
|
+
else:
|
|
206
|
+
self._dashboard.access_token = access_token
|
|
207
|
+
return self._dashboard
|
|
208
|
+
|
|
175
209
|
@property
|
|
176
210
|
def dev_portal(self) -> AsyncDevPortalClient:
|
|
177
211
|
"""Entitlement-gated staging-app minting (server-side only: needs the secret key)."""
|
|
@@ -347,6 +381,8 @@ class AsyncSpapsClient:
|
|
|
347
381
|
self._whitelist,
|
|
348
382
|
self._secure_messages,
|
|
349
383
|
self._dev_portal,
|
|
384
|
+
self._purchase_journeys,
|
|
385
|
+
self._dashboard,
|
|
350
386
|
self._issue_reporting,
|
|
351
387
|
self._metrics,
|
|
352
388
|
self._entitlements,
|