Skip to content

Commit 9933ba3

Browse files
HF-307: wire the two commercial add-on tokens, strictly additively
Per the 2026-08-12 packages meeting: `spreadsheet` backs the Spreadsheet Bundle add-on and grants Crud, UndoRedo, Clipboard and Batching ("chyba tez" batching - Kuba, 12.08); `import_export` grants FeatureId.ImportExport, a reserved grant with no gated method until HF-107 ships the feature. Additive only: a key naming neither add-on keeps every feature area it has today (the opt-in rule for keys carrying no feat:* tokens is untouched), so no real key can start throwing as a side effect of this change. The open product question - does a package key without the bundle keep CRUD once packages go live - stays open and is documented as such in the guide. Implemented by a prep-ship lane (task HF-307-addon-grants); verified here: license suite 165/165 under Jest, tsc --noEmit clean, eslint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PdHPZAjciZFWqGa19Yf7it
1 parent 7b5398d commit 9933ba3

3 files changed

Lines changed: 41 additions & 13 deletions

File tree

docs/guide/license-key.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ an id of their own. The licence covers built-in ids, so a plugin registered unde
6565
key does not include is treated as that built-in and stays unavailable — it will not be described and
6666
it evaluates to `#LIC!`. Pick an id the built-in catalogue does not use and this cannot happen.
6767

68+
Two commercial add-ons build on top of a package:
69+
70+
* **Spreadsheet Bundle** grants the CRUD API (adding, removing, and moving rows, columns, sheets,
71+
and cell contents), undo/redo, clipboard operations, and batching (`suspendEvaluation()` /
72+
`resumeEvaluation()`).
73+
* **Import/export** is reserved for a future release. HyperFormula doesn't have an import/export
74+
feature yet, so this add-on doesn't grant or restrict anything today.
75+
76+
In this release, not having either add-on doesn't restrict anything either: every key already
77+
grants the CRUD API, undo/redo, clipboard, and batching regardless of whether it names these
78+
add-ons.
79+
6880
::: tip
6981
To find out which package your key includes, check your order confirmation or
7082
[contact our team](contact.md). HyperFormula deliberately reports nothing about the contents of

src/license/LicenseEntitlement.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
/**
77
* Identifies a feature area of the public API that a license entitlement can gate.
88
*
9-
* `CustomFunctions` and `ImportExport` are reserved vocabulary: they exist so a license payload
10-
* is free to carry them, but no capability grant in this release maps to either of them yet.
11-
* HF-307 decision D1 drops function-registration gating (and the `CustomFunctions` grant) from
12-
* this release; `ImportExport` has no gated methods until HF-107 lands.
9+
* `CustomFunctions` is reserved vocabulary: it exists so a license payload is free to carry it,
10+
* but HF-307 decision D1 drops function-registration gating (and the `CustomFunctions` grant)
11+
* from this release, so no capability grant maps to it.
12+
*
13+
* `ImportExport` IS granted, by the `import_export` add-on token (2026-08-12 packages meeting) —
14+
* but it gates no public method yet, because HF-107 hasn't shipped the import/export feature it
15+
* would gate. The grant exists; the gate does not, yet.
1316
*/
1417
export const enum FeatureId {
1518
NamedExpressions = 'named_expressions',

src/license/capabilities.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,17 @@ export const FUNCTIONS_2_TOKEN = 'functions_2'
4444
export const FUNCTIONS_3_TOKEN = 'functions_3'
4545
/** Excel simulator package — the entire implemented catalog. */
4646
export const FUNCTIONS_4_TOKEN = 'functions_4'
47-
/** Spreadsheet add-on. Reserved: recognized, grants nothing yet — see {@link CAPABILITY_TABLE}. */
47+
/**
48+
* Spreadsheet Bundle add-on (2026-08-12 packages meeting). Grants {@link FeatureId.Crud},
49+
* {@link FeatureId.UndoRedo}, {@link FeatureId.Clipboard} and {@link FeatureId.Batching} — see
50+
* {@link CAPABILITY_TABLE}.
51+
*/
4852
export const SPREADSHEET_ADDON_TOKEN = 'spreadsheet'
49-
/** Import/export add-on. Reserved until HF-107 ships the feature it would gate. */
53+
/**
54+
* Import/export add-on (2026-08-12 packages meeting). Grants {@link FeatureId.ImportExport}, a
55+
* RESERVED grant: nothing in the public API is gated on it yet, because HF-107 hasn't shipped the
56+
* import/export feature it would gate.
57+
*/
5058
export const IMPORT_EXPORT_ADDON_TOKEN = 'import_export'
5159

5260
/**
@@ -197,11 +205,13 @@ const functions4Grant: CapabilityGrant = {
197205
* all five alongside the tier (that vocabulary predates feature tokens); legacy keys resolve to
198206
* the unrestricted entitlement and never consult this table.
199207
*
200-
* The two add-on tokens are RESERVED: recognized, so an issued key carrying one is not reported
201-
* as unrecognized, but granting nothing. `spreadsheet` has no agreed content yet — the packaging
202-
* proposal names a *package* "Spreadsheet" and the pricing task names a "Spreadsheet Bundle"
203-
* add-on, and it is not settled whether those are the same set; guessing would silently sell an
204-
* empty add-on or duplicate a whole tier. `import_export` has nothing to grant until HF-107.
208+
* The two add-on tokens, wired per the 2026-08-12 packages meeting: `spreadsheet` backs the
209+
* 'Spreadsheet Bundle' add-on and grants {@link FeatureId.Crud}, {@link FeatureId.UndoRedo},
210+
* {@link FeatureId.Clipboard} and {@link FeatureId.Batching} (Kuba: batching too, 12.08).
211+
* `import_export` backs the import-export add-on and grants {@link FeatureId.ImportExport} — a
212+
* RESERVED grant, since nothing in the public API is gated on it yet: HF-107 hasn't shipped the
213+
* feature it would gate. Both tokens stay recognized either way, so an issued key carrying one is
214+
* never reported as unrecognized.
205215
*/
206216
export const CAPABILITY_TABLE: ReadonlyMap<string, CapabilityGrant> = new Map([
207217
[CORE_TOKEN, coreGrant],
@@ -214,7 +224,10 @@ export const CAPABILITY_TABLE: ReadonlyMap<string, CapabilityGrant> = new Map([
214224
[CLIPBOARD_FEATURE_TOKEN, {functions: [], features: [FeatureId.Clipboard]}],
215225
[NAMED_EXPRESSIONS_FEATURE_TOKEN, {functions: [], features: [FeatureId.NamedExpressions]}],
216226
[BATCHING_FEATURE_TOKEN, {functions: [], features: [FeatureId.Batching]}],
217-
[SPREADSHEET_ADDON_TOKEN, {functions: [], features: []}],
218-
[IMPORT_EXPORT_ADDON_TOKEN, {functions: [], features: []}],
227+
[SPREADSHEET_ADDON_TOKEN, {
228+
functions: [],
229+
features: [FeatureId.Crud, FeatureId.UndoRedo, FeatureId.Clipboard, FeatureId.Batching],
230+
}],
231+
[IMPORT_EXPORT_ADDON_TOKEN, {functions: [], features: [FeatureId.ImportExport]}],
219232
])
220233

0 commit comments

Comments
 (0)