@hasna/skills 0.8.0 → 0.8.1

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.
package/README.md CHANGED
@@ -684,6 +684,118 @@ and version-skew contract: `docs/architecture/remote-client-pins-tags-sync.md`.
684
684
  For the reusable upstream contract, see
685
685
  `docs/architecture/reusable-skills-engine.md`.
686
686
 
687
+ ### Recurring consent SDK
688
+
689
+ The SDK exposes `previewRecurringConsent`, `getRecurringDraft`,
690
+ `activateRecurringConsent`, `listRecurringConsents`, `getRecurringConsent`,
691
+ `listRecurringOccurrences` and `revokeRecurringConsent`. These require a server
692
+ that explicitly advertises the version-1 recurring capability; an unavailable
693
+ server raises `RemoteRecurringUnavailableError`. This client does not create
694
+ local schedules or enable a server policy. Use `createRemoteSkillsClient` for the
695
+ existing selected-profile/API binding, or construct `RemoteSkillsClient` with an
696
+ explicit bearer and API URL. Each operation captures that connection and all
697
+ inputs before asynchronous work. An optional final `RemoteWorkspaceContext`
698
+ restricts it to an observed user and membership; profile files are unchanged.
699
+
700
+ `RecurringRequest` carries explicit cadence, lifetime, runtime limits and credit
701
+ and occurrence ceilings. A preview returns immutable terms, their hash, the
702
+ original quote and approval deadline; its quote states that admission reprices.
703
+ Draft retrieval retains those values even after expiry and never refreshes the
704
+ deadline. Activation requires the original draft ID and `RecurringActivation`:
705
+ `contractVersion: 1`, its exact `acceptedTermsSha256`, the literal acceptance
706
+ `authorize-recurring-credit-use`, and a caller-owned idempotency key. The client
707
+ reads the stored draft before submitting; the server independently requires
708
+ current fresh human authority. Client metadata cannot grant that authority.
709
+ Read operations require `schedules:read`, while preview and revocation require
710
+ `schedules:manage`; API keys cannot activate a grant. Consent read/history/revoke
711
+ preserve tenant-wide control, including retained grants from other deployments.
712
+
713
+ `RemoteRecurringUnconfirmedError` means a dispatched mutation could have
714
+ committed. Keep its original server/account, inputs, terms hash and request key;
715
+ explicitly reconcile that same identity with current authority. The client never
716
+ retries a POST, creates a replacement key or asserts rollback. After uncertain
717
+ revocation, inspect the original consent and occurrences; revocation does not
718
+ promise cancellation of an already authorized attempt. Exact domain not-found
719
+ responses return `null` only for draft/consent reads. Malformed or oversized
720
+ responses fail closed. Pages accept 1–100 items and an opaque cursor; a large
721
+ terms page can exceed the 64-MiB response bound, so request a smaller page
722
+ explicitly. JSON input is limited to 1 MiB and 64 nesting levels. Dashboard
723
+ approval and server enablement remain separate from these client interfaces.
724
+
725
+ ### Recurring consent from the terminal or MCP
726
+
727
+ `skills recurring` uses the same hosted SDK methods. Existing `skills schedule`
728
+ commands retain their local metadata and one-shot behavior. A compatible server
729
+ must already support recurring consent; these commands install no server policy,
730
+ daemon or default key scopes. Read/draft/history require `schedules:read`, and
731
+ preview/revocation require `schedules:manage`.
732
+
733
+ | Command | MCP tool |
734
+ | --- | --- |
735
+ | `recurring preview --request <file>` | `preview_recurring_consent` |
736
+ | `recurring draft <draft-id>` | `get_recurring_draft` |
737
+ | `recurring activate <draft-id>` | `activate_recurring_consent` |
738
+ | `recurring list` / `recurring get <consent-id>` | `list_recurring_consents` / `get_recurring_consent` |
739
+ | `recurring occurrences <consent-id>` | `list_recurring_occurrences` |
740
+ | `recurring revoke <consent-id> --confirm` | `revoke_recurring_consent` |
741
+ | `recurring recover --recovery-dir <original-directory>` | `recover_recurring_consent` |
742
+ | `recurring verification <draft-id> --email <email> --confirm` | `request_recurring_verification` |
743
+
744
+ Use the CLI's existing `--profile <name>` before the command, or the MCP host's
745
+ explicitly configured connection. Fresh approval needs an enrolled workspace
746
+ profile or both observed `--user-id` and `--membership-id`; those IDs restrict
747
+ current authority. The target, profile and credential are captured before prompts
748
+ and checked again before changes. No operation switches or overwrites saved
749
+ credentials. A normal API-key login alone cannot activate recurring spend.
750
+ Before requesting or verifying a code, the client checks the selected key's
751
+ current account email, trimming whitespace and ignoring case as the server does.
752
+ A different email is refused before the login endpoint can create an account.
753
+
754
+ The request file contains every explicit `RecurringRequest` field, including
755
+ JSON input/args, runtime and connector limits, cadence/start/expiry/grace, UTC-day
756
+ period, finish-authorized-attempt policy, all three credit ceilings and both
757
+ occurrence ceilings. No policy values are inferred. Preview and draft retrieval
758
+ show the original server terms/hash, quote, first due instants and approval
759
+ deadline. They create no run or credit reservation. Each grant adds its own
760
+ budget; an occurrence reprices within the approved limits.
761
+
762
+ To activate, provide `--accepted-terms <original-sha256>`,
763
+ `--idempotency-key <original-key>`, `--recovery-dir <new-absolute-directory>`,
764
+ `--email <email>` and `--confirm`. A terminal displays the complete immutable
765
+ draft and requires typing `authorize-recurring-credit-use`, then requests a
766
+ fresh code and reads it masked. For JSON or noninteractive use, also supply
767
+ `--acceptance authorize-recurring-credit-use --code-stdin`; request the code
768
+ first with `recurring verification`. Do not put the code or session in argv.
769
+ Cancellation/EOF does not grant consent. The server independently verifies fresh,
770
+ eligible, non-impersonated human authority and the original terms.
771
+
772
+ MCP activation takes the same original draft, approval object, recovery directory
773
+ and explicit `confirm: true`, plus account email and a fresh code. The MCP host
774
+ may retain supplied code arguments in its history; the masked terminal flow
775
+ avoids that disclosure. No tool returns or stores the resulting session. A tool
776
+ confirmation boolean or API key never substitutes for verified human approval.
777
+
778
+ Activation and revocation require a new recovery directory under an existing
779
+ canonical parent. It is created privately and contains the original server,
780
+ profile, account/membership, draft/hash/approval key or consent ID and attempt
781
+ state. It contains no bearer, OTP or raw input payload. Preserve it after errors;
782
+ unknown mutation outcomes exit 2 in the CLI and set MCP `isError` with
783
+ `outcomeUnknown: true`. Read-only `recover` never resubmits. Explicit
784
+ `recover --confirm` reuses the original activation key/terms and fresh approval,
785
+ or the same revoked consent; it never creates a replacement request. An expired
786
+ draft or lost current authority does not resolve an earlier unknown outcome.
787
+ Aliased, replaced, malformed or locked recovery directories refuse changes.
788
+
789
+ List/history expose one page (1–100 items, default 20) and the unchanged opaque
790
+ cursor. Consent output includes period/total reserved and settled credits,
791
+ admitted counts, ceilings, deployment and next due time; history includes stable
792
+ occurrence/run IDs, outcomes, refusal reasons and allocation state. All hosts
793
+ read the same server identities. Revocation reports residual authorized exposure
794
+ and does not promise cancellation/refund of an already authorized attempt.
795
+ Cancellation is separate. A lost preview response has no draft lookup key:
796
+ report that uncertainty and explicitly choose any new preview, without silently
797
+ turning it into an activation.
798
+
687
799
  ## Portable Skills
688
800
 
689
801
  Portable skills live under `~/.hasna/skills/installed/<name>/` and follow the
@@ -1055,7 +1167,7 @@ src/
1055
1167
  |---|---|---|
1056
1168
  | Catalog skills | 0 | `SKILLS.length` (`src/lib/registry-data/`) |
1057
1169
  | Categories | 17 | `CATEGORIES` (`src/lib/registry-types.ts`) |
1058
- | MCP tools | 72 | `tools/list` against a live `buildServer()` |
1170
+ | MCP tools | 81 | `tools/list` against a live `buildServer()` |
1059
1171
 
1060
1172
  Every number in this table is re-derived from the source tree on each test run by
1061
1173
  `src/lib/readme-derived-counts.test.ts`, so a drifted figure fails a test rather