Subscription Plans

Subscription Plans

This document serves as a list of the subscription plans which should be avaliable to be purchased, along with the tools they offer, limits, price and usage restrictions.

See:

In short, for organisations and users, the Subscriptions and Plans structure should work as
follows: the organisation purchases N units of a plan, which entitles it to enable N members to
use the tools provided by that plan for that product. Seats are per product, so they cap how
many members may be enabled for that product — not how many may use it at the same instant.

Enabled members are subject both to a concurrency cap and to volume limits over time
(MAX_CALCULATIONS_PER_DAY and MAX_JOB_PER_WINDOW), the latter applying to the non-Pro plans.

Tools
Tool Analysis
GLASS_CHECKER_STATIC Static Analysis
GLASS_CHECKER_COLD_BENDING Static Analysis
GLASS_CHECKER_IMPACTOR Dynamic Analysis
GLASS_CHECKER_THERMAL Thermal Analysis
Plans
  • GLASSS Free: Free tier plan which is authomatically associated to an organization on its creation. Perpetual.
  • GLASSS Students: Free tier plan for students. Term of 1 year, renewed by academic-eligibility re-verification rather than payment (see Subscription Lifecycle §13).
  • GLASSS Base: Base tier plan. Has higher limits in respect to the Free plan and removes Maffeis logos from the graphs and from the report, where it's replaced by the organization's own logo.
  • GLASSS Pro: Tier plan for professional usage. Has same benefits of Base tier, with even higher limits and access to all glass analysis types.

Plan Rank and Category

Rank orders the commercial ladder; category carries the semantics. Exactly one plan per product
has category Free — that plan is the fallback target on expiry. See
Subscription Lifecycle §4.

Plan Category Rank Term
GLASSS Free Free 0 perpetual
GLASSS Students Academic 0 1 year
GLASSS Base Commercial 1 1 year
GLASSS Pro Commercial 2 1 year

Plan Tools

GLASS_CHECKER_STATIC GLASS_CHECKER_COLD_BENDING GLASS_CHECKER_IMPACTOR GLASS_CHECKER_THERMAL
GLASSS Free ✔️
GLASSS Students ✔️
GLASSS Base ✔️
GLASSS Pro ✔️ ✔️ ✔️ ✔️

Plan Limits

GLASSS Free GLASSS Students GLASSS Base GLASSS Pro
Maximum Bounding Box Area [mm²] 40000000 40000000 40000000 40000000
Maximum Packages 2 3 3 5
Maximum Layers 8 10 13 15
Maximum Holes 5 5 8 10
Maximum 2D Mesh Nodes 8000 8000 10000 12000
Maximum 3D Mesh Nodes 32000 32000 40000 48000
Maximum Barrier Loads 2 2 2 2
Maximum Point Loads 2 2 2 2
Maximum Job Per Window 2 2 4 No Limit
Maximum Calculation Per Day 10 100 20 No Limit
Maximum Concurrent Calculations 1 1 1 1

Plan Tool-specific Limits

GLASSS Free GLASSS Students GLASSS Base GLASSS Pro
Maximum Combinations per Static Analysis 30 30 50 100
Maximum Steps Number for Dynamic Analysis ✖️ ✖️ ✖️ 200
Price

A single annual price per plan (matching the seeded Plan.Price / DurationInMonth = 12).

Annually
GLASSS Free Free
GLASSS Students Free
GLASSS Base 100€ / per unit
GLASSS Pro 1000€ / per unit

There should be a 7-day free trial on first time a paid plan is purchased. Since the two priced
plans have different tools access, the free trial should be applied the very first time each plan
is purchased. Eligibility is derived from the organisation's subscription history, so a lapsed
trial is never re-granted — see Subscription Lifecycle §11.

Seats Per Plan Unit
Seats
GLASSS Free 1
GLASSS Students 1
GLASSS Base 1
GLASSS Pro 1
Paddle Mapping (Sandbox)
Plan Paddle Product ID Billing Price (per seat) Paddle Price ID
GLASSS Free (no Paddle product — internal only, 1 seat, auto-assigned) Free
GLASSS Students (no Paddle product — internal only, 1 seat, free) Free
GLASSS Base pro_01ky9b9rgf9n85yrpp9zgan7q4 Annual 100 € pri_01ky9bdktysm0v4egbkeytsxhv
GLASSS Pro pro_01ky9bdm01h3z5gemhyzr2c00n Annual 1000 € pri_01ky9bdm8kehhe735nzvqahw4w

The Paddle price IDs above were created for the earlier 50 €/500 € annual figures and need
re-issuing for the 100 €/1000 € prices.

  • Tax category: saas.
  • Currency: EUR.
  • Seat quantity allowed per subscription item: minimum 1, maximum 1000.

Things still to be handled at the application level, not in the Paddle catalog:

  • Seats: quantity purchased at checkout is the seat count for the specific plan.
  • 7-day trial: not baked into these prices — apply it dynamically at subscription-creation time (via a non-catalog price override carrying trial_period), only the first time an organization subscribes to each plan (Base and Pro tracked separately).
  • Free/Students: stay purely internal Plan rows with no Paddle product, as agreed.
Subscription Lifecycle

Subscription Lifecycle

This document describes the lifecycle of subscriptions inside the application: every phase a
subscription goes through, every scenario that must be handled, and the behaviour required at
each step.

It is a specification, not a description of the current implementation. Where today's
behaviour is mentioned it is explicitly marked (current behaviour) so it cannot be mistaken
for the specification.

See:


Part I — Foundations

1. Scope and invariants

Everything in this document is scoped per product. An organization holds at most one active
subscription per product, so every phase below describes what happens to one product's
subscription. An organization with GLASSS and OSM subscriptions runs two independent lifecycles.

The following invariants hold everywhere and are not restated in each chapter:

  1. Entitlements are derived, never authored. An entitlement is a materialised projection of
    (subscription, plan). It is never edited directly, and it can always be recomputed from
    scratch. Administrators change subscriptions; entitlements follow.
  2. A subscription that is not Active grants nothing, regardless of what entitlement rows
    exist for it. Stale rows are a cleanliness problem, never an access problem.
  3. null means unlimited, for seats and for every limit value. The absence of a limit is
    not the same as a limit of zero.
  4. Status never encodes notification state. Whether a warning email has been sent is
    tracked separately. Using status as a "have we emailed yet?" latch couples billing state to
    mail delivery and silently changes access.
  5. One tool belongs to exactly one product. A tool is never shared across products, so the
    product that grants a tool — and therefore the plan whose limits apply to it — is always
    unambiguous.
  6. Derived state must be fully recomputable. No lifecycle outcome may depend on an event
    being delivered exactly once; a complete sweep must be able to rebuild everything from
    (subscription, plan).
2. Subscription identity: the successor chain

A subscription is not a mutable row. It is a chain of period records, each describing one
plan, one quantity and one term. Every plan change, quantity change or term change closes the
current record and opens a successor
that links back to its predecessor.

  • Exactly one record in a chain is Active at any moment.
  • A record has at most one successor, enforced by a uniqueness constraint on the predecessor
    reference.
  • Closing a record and opening its successor is a single atomic operation. The
    "one Active per (organization, product)" rule means there is otherwise an instant with either
    two Active records or none, and "none" leaves a paying customer with no entitlements and no
    seats.

This model is what makes the rest of the document expressible:

It gives you Because
History — "what was this organization entitled to on 12 March, and what did it pay?" Closed records are never overwritten
Trial eligibility The chain records whether this organization ever held a trial on this plan
Proration The record being closed carries the term and price the refund/charge is computed against
Exactly-once renewal Renewal creates a successor, and a record can only have one — a second concurrent attempt violates the constraint and stops

That last point deserves emphasis: exactly-once renewal needs no separate idempotency table and
no distributed lock. It falls out of the one-successor constraint. Two application replicas
running the renewal pass concurrently will both find the same expired record, and exactly one
will succeed in attaching a successor.

3. Status semantics

Every status must answer five independent questions. These are the questions the readers of the
system actually ask, and they are the questions that a single "is it active?" boolean cannot
answer.

Status Grants tools Occupies the Active slot Counts toward seats Bills / renews Terminal
Draft No No No No No
Active Yes Yes Yes Yes No
Expiring Yes Yes Yes No No
Suspended No Yes No Retry only No
Cancelled No No No No Yes
Expired No No No No Yes

Meanings:

  • Draft — a record that exists but has not taken effect: created and awaiting its first
    successful payment, or pre-created for a future start. It grants nothing and does not reserve
    the product slot.
  • Active — the normal state. Grants its plan's tools, consumes the slot, provides seats, and
    renews at term end if auto-renew is on.
  • Expiringstill fully valid, but will not renew. This is the state of a subscription
    the customer has unsubscribed from: they keep everything they paid for until the term ends.
    Access is unchanged from Active; only the renewal behaviour differs.
  • Suspended — payment has failed and the dunning window is open. All access is blocked
    (no read-only mode, no export). The record still occupies the product slot, so no competing
    subscription can be created, and it is recoverable: a successful payment inside the window
    returns it to Active.
  • Cancelled — terminated before its natural end (immediate cancellation, refund,
    chargeback, organization deactivation). Terminal.
  • Expired — reached its end date without renewing. Terminal.

Two consequences worth stating explicitly:

  • Expiring and Suspended both occupy the Active slot but differ completely on access. Slot
    occupancy is about uniqueness, not about permission; conflating the two is what makes
    "is it active?" an unanswerable question.
  • (Current behaviour: Expiring is set seven days before the end date purely to avoid sending
    a duplicate warning email, and because every reader gates on Status == Active, this revokes
    all tools and drops seats to zero a week early. Under this specification, "warning sent" is
    tracked separately — see invariant 1.4 — and Expiring means only "will not renew".)
4. Plan taxonomy: rank, category, and what "upgrade" means

"Upgrade" and "downgrade" decide whether the customer pays today or waits until period end,
so they are pricing decisions and must be defined precisely rather than inferred.

Each plan carries two independent attributes:

  • Rank — a pure ordinal placing the plan on its product's commercial ladder.
  • CategoryFree, Commercial or Academic. Category carries the semantics; rank
    carries only the ordering. Keeping them separate means a new category never disturbs the
    ladder.
Plan Category Rank
GLASSS Free Free 0
GLASSS Students Academic 0
GLASSS Base Commercial 1
GLASSS Pro Commercial 2

Classification of a change from plan A to plan B:

Condition Classification Payment timing
Both Commercial, rank(B) > rank(A) Upgrade Immediately, prorated
Both Commercial, rank(B) < rank(A) Downgrade Deferred to period end
Both Commercial, rank(B) = rank(A) Lateral Deferred to period end
A is Free or Academic, B is Commercial Term creation (chapter 6) Immediately, full term
B is Free or Academic Term destruction (chapter 6) No charge

Rules:

  • Comparability applies within Commercial only. Free and Academic plans are not ranked
    against commercial tiers; moving to or from them is a term operation, not a tier move.
  • Exactly one plan per product has category Free. That plan is the fallback target for
    expiry and unsubscription (chapters 19–20). Without this marker, "if there is a free plan
    available for that product" is ambiguous — GLASSS has two free plans.
  • A product need not have a Free plan. Chapters 19–20 define what happens when it does not.
5. Membership and seat model

Seats are per product. There is no organization-wide seat limit.

Access requires two independent things to be true, and they are separate levels:

Level 1 — organization activation. A member of an organization is activated or
deactivated. This is organization-wide and uncapped: an organization may invite and
activate as many members as it likes.

Level 2 — product enablement. An activated member may be enabled for individual products
the organization holds a subscription for. This level is capped, by that product's seats.

Rules:

  • A member may be enabled for any number of products simultaneously. There is no restriction
    beyond each product's own cap.
  • Deactivating a member organization-wide cascades: every product enablement they hold is
    disabled. Reactivating them does not restore those enablements — the Owner re-enables
    deliberately.
  • A seat is consumed by a product enablement, not by organization activation and not by a
    pending invitation.
  • An organization may have zero members enabled for a product. Nothing prevents that.
  • The Owner is not exempt from seat accounting. An Owner who is not enabled for a product simply
    has no access to it — organization management does not depend on product enablement, so an
    Owner can administer a product they cannot use.

Seat capacity for a product is:

Subscription.Seats  =  Plan.Seats × Subscription.PlanQuantity        (null ⇒ unlimited)

Subscription.Seats is a stored denormalised copy of that product, kept so that reading
capacity does not require loading the plan. It is not an override. It must be recomputed in
the same atomic operation
as any plan or quantity change, or it drifts from the truth.

Enforcement is preventive, at a single point. The cap is checked when a member is enabled
for a product — whether that happens on invitation acceptance or by an explicit action. It is
not a periodic correction. A background sweep may verify the invariant, but it is never the
mechanism by which the cap is applied.

(Current behaviour: enforcement is entirely retroactive — invitation acceptance and manual
activation perform no check at all, and the only correction happens inside the expiry job.)

Consequence: entitlement checks are member-aware

Because level 2 gates access, the question the software asks is no longer "may this organization
use tool X?" but "may this member, in this organization, use tool X?" Both must be true: the
organization is entitled to the tool through a subscription, and the member is enabled for the
product that grants it.

(Current behaviour: the entitlement check takes only an organization id. Making it member-aware
is a change to the core licensing API and to its caching, which currently caches one tool set
per organization.)

6. Term operations

Every phase in Part II is a composition of four operations. Naming them removes a genuine
ambiguity in the lifecycle: whether moving from Free to Base is "taking out a new subscription"
or "upgrading a tier". It is neither — it is term creation.

Operation What it does Typical trigger
Term creation Assigns a start date, an end date, an auto-renew setting and a price where none existed. Free is perpetual (EndDate = null), so moving from Free to a paid plan creates a term. First paid purchase, trial start
Term extension Moves the end date forward by the plan's duration, leaving plan and quantity untouched. Renewal
Term alteration Changes plan or quantity within an existing term. Upgrade, downgrade, quantity change
Term destruction Removes the term: back to perpetual (EndDate = null, auto-renew off) on the Free plan, or to nothing at all if the product has no Free plan. Expiry, unsubscription

Invariants tying terms together:

  • AutoRenew = trueEndDate ≠ null. An auto-renewing perpetual subscription can never
    renew, because nothing ever triggers it.
  • Plan.DurationInMonth = nullEndDate = null. A perpetual plan has no term to end.
  • A perpetual subscription can never be renewed, dunned or expired. Any deferred change attached
    to one would wait forever, so deferred changes are only meaningful on fixed terms.
  • Entitlement validity is a pure function of the term. Every one of the four operations
    above re-derives the entitlement window. Advancing an end date without re-deriving leaves
    entitlements expiring on the old date — a renewed, paying customer losing access the next
    day. (Current behaviour: renewal advances the end date without re-deriving.)
7. What a plan change actually changes

The shared operation the draft called Plan change is not only about entitlements. It acts on
five axes, and a phase that touches one must state its effect on all five:

  1. Entitlements — which tools the organization may use.
  2. Resolved limits — the numeric caps applied at runtime (per-day, per-window, concurrency,
    and the structural caps on layers, holes, packages, loads, mesh nodes, bounding-box area,
    combinations, time steps).
  3. Seat capacity — recomputed, with any excess enablements disabled (chapter 5).
  4. Branding — whether reports and graphs carry the organization's logo or the Maffeis logo.
  5. Billing and notification state — price, term, auto-renew, and what the customer is told.

This matters because of a fact easy to miss: GLASSS Free and GLASSS Base grant an identical
tool set.
The most common purchase in the system therefore changes no entitlements at all.
Its entire value is in axes 2 and 4. A specification that treated "plan change" as an
entitlement operation would describe the one axis that does not move.

Every plan change ends with cache invalidation across all five axes, performed after the
change commits, never before. Any derived value that is cached must have a bounded lifetime; no
cached entry may be immortal.

8. Usage metering scope

Usage counters (per-day, per-window, concurrency) are runtime state, and their identity must
be chosen carefully, because it determines what resets them.

The counter's identity must match the scope of the limit being enforced, and must never
include the plan.

  • Plan-wide limits — per-day, per-window, concurrency — scope to
    (organization, member, product). One budget shared across every tool the subscription
    grants. Keying them per tool would multiply the allowance by the number of tools in the plan.
  • A genuinely tool-scoped limit scopes to (organization, member, product, tool).
  • Product, not plan, is the stable axis. There is at most one active subscription per
    product and the product survives every plan change, so:
  • a plan change or trial start cannot hand out a fresh daily allowance, and
  • a concurrency slot taken under one plan cannot be orphaned by a plan change mid-run,
    because acquire and release resolve the same key.
  • The plan supplies only the limit value, never part of the key.

Carry-over rule. Consumption carries across a mid-period plan change, and the new plan's
value applies to the existing counter. A downgrade can therefore leave a member already over
their new limit and blocked for the remainder of the period. This is intended: the alternative
is a reset that can be farmed by bouncing plans.

Business-day definition. The system has exactly one definition of "day" for quota purposes,
and one answer to when a subscription starts and ends. (Current behaviour: usage quotas roll at
Europe/Rome midnight while subscription dates are UTC, so the "usage day" and the "subscription
day" are different days for part of every night.)


Part II — Phases

Each chapter states: the trigger, the records closed and opened, the operations from
Part I applied, the side effects, and the failure branches.

9. Organization creation → initial Free subscription

Trigger. An organization is created.

Records. A first Active record is opened on the product's Free plan, quantity 1, perpetual
(EndDate = null, auto-renew off).

Operations. Term creation with a perpetual term.

Side effects. Entitlements derived from the Free plan's tools; seat capacity set to the Free
plan's seats; the creating user becomes Owner.

Requirements.

  • The organization and its initial subscription are created atomically. An organization
    without a subscription has no seats, so a window in which it exists un-subscribed is a window
    in which nobody can be enabled for anything.
  • Organizations exempt from this rule (the Maffeis internal organization, on internal-only
    plans) are named explicitly rather than special-cased silently.
  • If the product has no Free plan, no subscription is created and the organization simply holds
    none for that product.

Failure branches. If subscription creation fails, organization creation fails with it.

10. Subscribing to a product not yet held

Trigger. An organization buys a product for which it holds no subscription.

Note this is genuinely distinct from chapter 15 (upgrade). Because every organization receives a
Free GLASSS subscription at creation, it is always subscribed to GLASSS — so for GLASSS this
phase never occurs, and Free → Base is chapter 15's term creation instead. This phase applies to
a second product.

Records. A new chain begins: an Active record on the chosen plan.

Operations. Term creation.

Side effects. All five axes of chapter 7. Seat capacity appears where there was none, so
members may now be enabled for this product.

Failure branches. Payment declined → the record stays Draft and grants nothing; nothing
else in the organization changes.

11. Trial

Trigger. An organization purchases a paid plan it has never trialled.

Records. A record with IsTrial = true, on the target plan, with a term equal to the trial
length (7 days — see Subscription Plans).

Operations. Term creation.

Eligibility. Derived from the chain history: an organization is eligible for a trial on a
plan if no record in its history for that plan carries IsTrial = true. Consequences:

  • Base and Pro are tracked separately, as separate plans.
  • A lapsed or cancelled prior trial is never re-granted.
  • Academic plans do not consume commercial trial eligibility: Academic ranks alongside Free, so
    a Students organization remains eligible for the Base and Pro trials.
  • Trial eligibility keys on the organization, and organization VAT id and email are unique
    (chapter 25), which limits — but does not eliminate — farming by creating new organizations.
    Accepted residual risk.

Side effects. Full entitlements and limits of the target plan for the trial's duration. The
trial grants real access, not a restricted preview.

End of trial. Two outcomes:

  • Conversion — auto-renew is on and payment succeeds: the trial record closes and a
    successor opens on the same plan with a full paid term. Term extension in effect, but as a new
    record because plan/term changed.
  • Abandonment — the customer unsubscribed during the trial, or conversion payment failed
    past the dunning window: chapter 19 applies.

Failure branches. Conversion payment fails → chapter 14 (dunning), from which the record may
still recover.

12. Automatic renewal

Trigger. An Active record with auto-renew on reaches its end date.

Records. The current record closes as Expired; a successor opens as Active with the same
plan and quantity and a term extended by the plan's duration.

Operations. Term extension.

Side effects. Entitlement validity re-derived to the new term (chapter 6). Seat capacity
recomputed — unchanged unless a deferred change applies. If a deferred change is pending
(chapter 22), it is applied as part of this renewal: the successor opens on the pending plan
and quantity, and the pending intent is cleared.

Requirements.

  • Exactly-once. Renewal must produce exactly one successor per period even with several
    application replicas running the pass concurrently. The one-successor constraint of chapter 2
    provides this.
  • Anchoring. The new term is computed from the previous term's end, not from the date the
    job happened to run, so a late job does not silently shorten the customer's term. A term
    boundary must not drift because of deployment timing.
  • Catch-up. If the job has not run for several periods, renewal repeats until the term
    covers today. A record whose term has passed but which has not yet renewed is
    Active-but-uncovered and must not grant access on the strength of its status alone.

Failure branches. Payment fails → chapter 14.

13. Academic renewal by re-verification

Trigger. An Academic (Students) record approaches its end date. Academic terms are one year.

Records. As chapter 12, but the gate is eligibility, not payment.

Operations. Term extension.

Requirements. Near the end of the term — and while the record is Suspended, if it reached
that state — the member must be able to re-establish academic eligibility: supplying an academic
email address that can be verified, to which a verification code is sent. Successful
verification renews the term.

Deferred: this verification flow is specified but not built. Administrators renew Academic
subscriptions manually in the meantime.

Failure branches. No re-verification by the end of the dunning window → chapter 20 (expiry),
falling back to the product's Free plan.

14. Payment failure and dunning

Trigger. A charge fails — at renewal, at trial conversion, or on an immediate upgrade
payment.

Records. The record moves to Suspended. It is not closed: it stays in the chain and
keeps occupying the product slot, so no competing subscription can be created while the
situation resolves.

Operations. None on the term. The term is untouched; only status changes.

Side effects.

  • All access is revoked for the duration: no tools, no read-only mode, no export.
  • Seat capacity drops to zero for the product, but enablements are not discarded — they are
    suspended along with the subscription, so recovery restores the previous arrangement rather
    than requiring the Owner to rebuild it.
  • The customer is notified, with the consequence and the deadline stated plainly.

Dunning window: 2 days.

  • Payment succeeds within the window → back to Active, entitlements and limits rebuilt, seats
    and enablements restored.
  • Window elapses → chapter 20 (expiry), falling back to the product's Free plan.
15. Upgrade

Trigger. The customer moves to a higher-ranked Commercial plan (chapter 4).

Records. The current record closes; a successor opens on the new plan.

Operations. Term alteration — or term creation when moving from Free or Academic, where
no term existed.

Side effects. All five axes of chapter 7. Note again that Free → Base changes no
entitlements: the effect is entirely in limits and branding.

Payment. The difference for the remaining period is charged immediately. Coming from a
perpetual Free plan there is no "remaining period" and no prior price, so the charge is a full
term at the new plan's price.

Term anchoring. Whether the upgrade keeps the original renewal anniversary or starts a fresh
term from today must be stated per product, and it must be the same answer as the one the
provider applies, or our end date and the provider's billing period diverge permanently.

Failure branches — each needs an explicit outcome:

  • Payment declined → no successor is opened; the customer stays on the current plan and is
    told why.
  • Payment succeeded but the change failed → the customer has paid for something they did not
    receive. This requires a compensating action: retry the change, or refund. It must never be
    left silent.
  • Two concurrent upgrade attempts (a double-clicked button, two tabs) → exactly one
    succeeds. Pricing is computed against a specific version of the record, and the change is
    conditional on that version still being current.
16. Downgrade

Trigger. The customer moves to a lower-ranked Commercial plan.

Records. Nothing closes now. The intent is recorded as a deferred change (chapter 22) and
applied at the next renewal, which opens the successor on the lower plan.

Operations. At effect time: term extension combined with term alteration.

Side effects. Until the period ends, nothing changes — the customer keeps the tools,
limits, seats and branding they paid for. At effect time, all five axes of chapter 7 apply, and
seat reduction (chapter 5) runs if the new plan provides fewer seats.

Payment. No charge now; the next renewal is at the lower price.

Failure branches. See chapter 22 for what happens if the intent is superseded, cancelled, or
if the target plan is retired or repriced before it takes effect.

17. Quantity increase

Trigger. The customer buys more units of their current plan.

Records. The current record closes; a successor opens with the higher quantity.

Operations. Term alteration.

Side effects. Seat capacity recomputed upward (chapter 5), and Subscription.Seats
recomputed in the same operation. Entitlements are unaffected — quantity does not change which
tools are granted.

Raising the cap does not enable anybody. It grants the right to enable more members;
enabling them stays a deliberate Owner action. In particular, members previously disabled by a
reduction are not automatically re-enabled.

Payment. The difference for the remaining period is charged immediately.

Failure branches. As chapter 15. In particular, if the quantity-increase charge fails after
members have already been enabled into the new seats, the rollback must disable them again —
the seat change and the payment outcome are one unit.

18. Quantity decrease

Trigger. The customer reduces the number of units.

Records. Nothing closes now; the intent is recorded as a deferred change (chapter 22) and
applied at the next renewal.

Operations. At effect time: term extension combined with term alteration.

Side effects. At effect time, seat capacity is recomputed downward and seat reduction
(chapter 5) runs.

Seat reduction rule. When the cap drops below the number of enabled members, every
enablement for that product is disabled
. The Owner then re-enables the members they want,
within the new cap.

This is deliberately simple. The alternative — automatically choosing which colleagues lose
access — makes the system arbitrate a decision that belongs to the customer, and any ordering
rule (newest first, least recently active) needs state that must be maintained correctly to
avoid disabling the wrong people. Disabling all and letting the Owner rebuild is predictable and
never silently wrong.

Ordering requirement. The quantity change and the seat reduction are one atomic unit.
Reducing the quota first lets a concurrent enablement fill a seat that was about to be freed;
reducing seats first evaluates the excess against the old, higher quota and frees nothing.

19. Cancellation / unsubscribe

Trigger. The customer unsubscribes.

Records. The record moves to Expiring. It does not close, and nothing else changes.

Operations. None yet. Auto-renew is turned off.

Side effects. None until the term ends: the customer keeps everything they paid for. They
are told when access will change and what it will change to.

At term end → chapter 20.

Un-cancelling. Re-enabling auto-renew before the term ends returns the record to Active.
Nothing has been lost, because nothing was closed.

Mid-trial unsubscription follows the same path: the trial runs to its end, then chapter 20
applies.

20. Expiry and the Free fallback

Trigger. An Active or Expiring record reaches its end date without renewing — because
auto-renew was off, or because a dunning window elapsed (chapter 14), or because Academic
re-verification did not happen (chapter 13).

Records. Two cases:

  • The product has a Free plan (category Free, chapter 4): the current record closes as
    Expired, and a successor opens as Active on the Free plan, quantity 1, perpetual
    (EndDate = null, auto-renew off) — both in one transaction.
  • The product has no Free plan: the current record closes as Expired and no successor is
    created
    . The organization simply holds no subscription for that product.

Operations. Term destruction, then term creation in the first case.

Side effects — in this order, and resumable:

  1. Close the paid record, so it stops granting anything.
  2. Open the Free successor (or none).
  3. Re-derive entitlements from the new plan.
  4. Recompute seat capacity and Subscription.Seats; run seat reduction (chapter 5).
  5. Invalidate caches across all five axes.

The ordering matters. Getting it wrong produces either the old plan's tools with the new plan's
limits, or — the expensive one — the new plan's limits with the old plan's tools, which is
over-entitlement that costs money. If the sequence is interrupted, the safe partial state is one
where access has already been reduced but the new record is not yet fully built; never the
reverse.

Notification. The customer is told the term ended, what they have now, and what they lost.

21. Reactivation after lapse

Trigger. An organization sitting on the Free plan (or holding nothing) buys a paid plan
again.

Records. The Free record closes; a successor opens on the paid plan. Where the organization
held nothing, a new chain begins.

Operations. Term creation.

Requirements.

  • The Free record must vacate the Active slot in the same transaction that opens the paid
    one (chapter 2).
  • Trial eligibility is not restored by the lapse. The chain still records the earlier trial,
    so a returning customer who trialled before does not trial again (chapter 11).
  • The price is the plan's current price, not the price they paid before.
  • Data deleted at any earlier point is not restored. Reactivation restores entitlement, not
    content.

Part III — Cross-cutting concerns

22. Deferred changes

Downgrades (16) and quantity decreases (18) take effect at period end, so the intent must live
somewhere between request and effect. A subscription therefore carries a pending change:
a pending plan, a pending quantity, and the date it takes effect.

Division of authority. We are authoritative for what the next period looks like; the
billing provider is authoritative for amounts and when the charge happens. Both sides hold a
version of the schedule, so chapter 23 covers disagreement.

Scenarios that must be handled:

  • Superseded intent. A downgrade followed by an upgrade before period end: the upgrade takes
    effect immediately (chapter 15) and clears the pending downgrade. Last instruction wins;
    intents do not queue.
  • Repeated intent. A second downgrade replaces the first.
  • Cancelling the intent. The customer may withdraw a pending change before it takes effect
    and stay on their current plan.
  • Interaction with unsubscription. A pending downgrade plus auto-renew off: expiry wins.
    There is no renewal for the downgrade to attach to, so chapter 20 applies and the pending
    intent is discarded.
  • Immediate change layered on a pending one. A quantity increase (immediate) while a
    downgrade is pending: the increase applies to the current plan and price now, and the
    pending downgrade still takes effect at period end — carrying the new quantity unless the
    pending change specifies its own.
  • The target is retired or repriced before the effect date: chapter 24.
  • The effect date is missed because the job did not run: the change applies at the next
    opportunity, and the customer is not charged for the gap.
  • What "current plan" means during the window. Everywhere the customer can see — UI, limits,
    entitlements, branding — the answer is the plan they are on now. The pending change is shown
    as scheduled, never as current.
  • Perpetual subscriptions cannot carry a pending change, because nothing would ever apply it
    (chapter 6).
23. Provider reconciliation and disagreement

Money lives with the billing provider; entitlement lives here. The two must be reconciled, and
they will disagree.

  • Authority. State which side owns each field. Plan price and currency exist in both places;
    one is authoritative and the other is a display copy. Likewise the term end: either it is our
    arithmetic or it is the provider's current period end, and mixing them makes them drift —
    particularly on month-end anniversaries, where repeated month arithmetic loses the anchor
    permanently (31 January → 28 February → 28 March, forever).
  • Callback ordering. Callbacks arrive out of order, more than once, or before the checkout
    redirect that caused them. Every callback is idempotent and safe to replay, and applying an
    older one must not undo a newer one.
  • Missing callbacks. A callback that never arrives must not leave a paid customer without
    access. A periodic sweep compares both sides.
  • Changes made at the provider. The customer may change plan, quantity or payment method in
    the provider's portal. Those changes must flow back.
  • Provider-side cancellation for its own dunning reasons, while our record says Active.
  • Refunds and chargebacks mid-period: whether access is revoked immediately (Cancelled) or
    the term is shortened.
  • Tax status changes. An organization's country or VAT id can change mid-term, altering the
    amount.
24. Catalogue changes

The lifecycle so far covers changes the customer initiates. Changes to the catalogue alter
what existing subscribers hold, and they need the same rigour.

Limits and tools are read live, not snapshotted at purchase. Editing a plan therefore
changes what every existing subscriber of that plan has, immediately and in both directions.
That is the intended behaviour, and it puts the burden on the following rules:

  • Plan.IsActive is a catalogue flag — never an entitlement or limit gate. Retiring a plan
    means "no longer purchasable". Existing subscribers keep resolving its tools and limits until
    their term ends. Revoking access is the job of subscription status, never plan status.

(Current behaviour, and the reason this rule is stated so firmly: limit resolution filters on
Plan.IsActive while entitlement resolution does not. Deactivating a plan therefore leaves
every subscriber with all their tools and
no limits at all, because an absent limit is read
as unlimited. Retiring a plan currently makes it strictly more permissive.)

  • An absent limit must never silently mean unlimited for a plan that is supposed to have
  • A tool added to a plan reaches existing subscribers, who gain access at the next
  • A tool removed from a plan revokes access for existing subscribers. Whether that is
  • A limit value changed applies live. Tightening a limit mid-term can put an existing
  • A price changed affects the next renewal of every subscriber on that plan. It requires
  • Catalogue edits must invalidate caches for every affected organization, not only for the
25. Organization lifecycle

Organizations are never hard-deleted. When an Owner deletes their organization — including
by deleting their own account (chapter 26) — the organization is deactivated:

  • the organization is marked inactive;
  • its data is deleted immediately, with no retention window: jobs, meshes, results,
    generated reports and uploaded logos;
  • current subscriptions are ended;
  • all members are removed from the organization; their user accounts are untouched;
  • financial and subscription history is preserved and remains visible to administrators.

So a deactivated organization retains its commercial record and nothing else. Reclaim restores
the organization and its billing history — never its data.

Ending subscriptions must cancel them provider-side. An organization deactivated here while
the provider keeps charging is the highest-consequence failure in this flow.

Deactivated organizations grant nothing. Organization status is part of the access decision;
a deactivated organization's subscriptions and entitlements are inert regardless of their own
status.

Identity and reclaim

VAT id and organization email are two separate unique keys. The organization email is the
organization's own field, supplied at registration — distinct from any member's login — and it
must be confirmed by email verification at registration, so that a reclaim always has a
known-good address to reach.

On a collision when creating an organization:

  • The existing organization is active → error: an organization is already using that data.
  • The existing organization is inactive → warning: an organization with this data already
    exists. The user must then supply the correct VAT id, and a verification code is sent to the
    original organization email. On successful validation the organization is reactivated
    and the requesting user becomes its Owner.

Because reclaim grants access to the prior billing history, that verification step is what
protects it. A user who supplies a VAT id or email that does not match the deactivated record is
shown a specific error rather than silently getting a fresh organization.

26. Account erasure

User accounts are fully deletable. Erasure is real: all records identifying the person are
removed. Two things survive, anonymised rather than deleted:

  • Authored work. Organization-owned jobs, meshes, results and reports are retained; the
    authorship reference is cleared. Erasing a departing employee must not destroy the company's
    engineering work.
  • Financial records. Subscription and purchase history is retained; the actor reference
    is cleared. This satisfies invoice-retention obligations while still erasing the person.

The same anonymise-don't-delete rule covers invitations: invitation records are never
deleted — they carry only an email address — and an already-accepted invitation simply has its
membership reference cleared.

The sole-Owner constraint. A user who is the only Owner of an organization cannot simply
vanish. Before erasure they must, for each such organization, either transfer ownership to
another member (where one exists) or confirm that the organization be deactivated (chapter 25).

This whole flow is atomic and all-or-nothing. The system enumerates every organization the
user owns and collects a decision for each. Nothing is deleted and no ownership is transferred
until every organization has been resolved
— abandoning the flow at any point leaves
everything exactly as it was. The per-organization choices are therefore collected as a pending
decision set and applied only on final confirmation.

Email reuse. After erasure the address is free. A new account may take it and inherits
nothing. This does not collide with organization reclaim, which keys on the organization's own
VAT id and email.

27. Owner and billing-contact lifecycle
  • At least one active Owner must always exist for an organization. Any operation that would
    leave none — removal, deactivation, erasure, or a seat reduction — is refused.
  • Authority and notification are different things. Who may change a subscription and who is
    told about it are often different people in a business. Both are stated per notification
    (chapter 31).
  • Ownership transfer mid-term changes neither the subscription nor its term.
  • An Owner not enabled for a product still administers it (chapter 5).
28. Data that exceeds reduced limits

After a downgrade — or a live limit tightening (chapter 24) — an organization can hold work that
violates its current limits: five packages on a plan allowing two, a mesh above the new node cap,
more combinations than the new plan permits.

This must be defined, because the limits are checked in two different places:

  • Structural caps (layers, holes, packages, loads, bounding box) are checked when editing,
    so existing work is not blocked from opening.
  • Analysis caps (mesh nodes, combinations, time steps) are checked when running, so
    existing work can be opened and then fails at run time.

The behaviour to specify, for each: is the work readable, re-runnable, exportable, or
locked? The default this document proposes: existing work remains readable and exportable,
but cannot be re-run until it is brought within the new limits, and the message says exactly
that rather than surfacing a bare limit error.

Related: already-generated reports carrying the organization's logo after a downgrade to a
plan without custom branding. They are historical documents and are not retroactively
re-branded.

29. In-flight work during transitions

A running analysis is never interrupted by a plan change, a seat reduction, a product
disablement, an organization deactivation or an account erasure. It runs to completion.

Subsequent operations are gated by their own logic and see the new state. This keeps the rule
simple and avoids half-finished computations, at the cost of a brief window in which work
completes under an entitlement that has just been withdrawn.

One requirement follows: releasing a concurrency slot must not depend on the member still
existing
, since the run may outlive their enablement or their account.

30. Ordering, idempotency and concurrency

Collected rules, each stated once here and referenced from the phases:

  • One subscription's transition is one atomic unit. Never batch several subscriptions into a
    single transaction — one failure must not roll back unrelated customers.
  • Vacate before insert, in one transaction. The one-Active-per-product rule means a
    successor cannot be inserted while the incumbent is still Active. Splitting the two risks an
    instant with no authoritative subscription.
  • A quota change and its seat reconciliation are one unit (chapter 18).
  • Invalidate caches after commit, never before, and never cache anything forever.
  • Rebuild entitlements atomically from a reader's perspective. A reader that observes the
    intermediate state of a delete-then-insert rebuild sees zero entitlements — and if it caches
    that, the customer loses access until the cache expires. Compute the new set and swap.
  • Every externally-triggered operation is idempotent. Replays, double submissions and
    retries are normal.
  • Renewal is exactly-once per period (chapter 2).
  • No lifecycle outcome depends on an event being delivered. Events make the system prompt; a
    complete periodic sweep makes it correct.
31. Notifications

Each transition states what the customer is told, and who is told. At minimum:

Transition Notification
Trial started What is included, and when it ends
Trial ending Ahead of the end date, with the conversion price
Renewal approaching Ahead of the charge, with the amount
Renewed Confirmation and the new term
Payment failed The consequence (all access blocked) and the deadline
Suspended Access is blocked and how to restore it
Upgraded / quantity increased What changed and what was charged
Downgrade / decrease scheduled What changes, and when
Deferred change applied Confirmation at the point it takes effect
Unsubscribed What they keep, until when, and what happens after
Expired What they have now and what they lost
Seats reduced That enablements were cleared and must be re-established
Price changing Advance notice, with the right to cancel first
Organization deactivated Confirmation, and what was irreversibly deleted

Notification state is tracked separately from subscription status (invariant 1.4).

32. Audit

The following must be reconstructable after the fact, for billing disputes and support:

  • what plan and quantity an organization held on any past date, and for how much;
  • who requested each change, and when;
  • which entitlements applied over which window;
  • the history of trials, so eligibility can be justified;
  • the financial record of a deactivated organization, and of an erased user's purchases in
    anonymised form (chapters 25–26).

The successor-chain model (chapter 2) provides most of this by construction: closed records are
never overwritten. What it does not provide by itself is actor and timestamp — who did it and
when — which must be recorded per transition.

33. Deferred work and deliberate non-goals

Every behavioural question is settled above. What follows is deliberately not yet built, listed
so an intentional gap is never mistaken for an omission:

  • Academic re-verification (chapter 13) — specified; administrators renew manually meanwhile.
  • Billing-provider integration — chapter 23 is specified against a provider that is not yet
    connected: no callback endpoint, no external subscription identifier.
  • Billing-interval switching — out of scope under the single-price model. Recorded only so a
    future reintroduction remembers the hazard it carries: a plan-keyed trial eligibility check
    would re-grant a trial on an interval switch.
  • Proration arithmetic — the when is specified (chapters 15, 17); the computation belongs
    with the provider integration.
  • Member-aware entitlement checks (chapter 5) — a change to the core licensing API, recorded
    as a design consequence.
  • Trial-abuse hardening beyond uniqueness — VAT id and email uniqueness (chapter 25) reduce
    but do not eliminate farming across genuinely distinct organizations. Accepted residual risk.
Subscription Architecture

Subscription Architecture

This document describe the structure of the subscription system inside the application.

See:

1. System Objective

The portal provides engineering calculation tools that can be accessed via:

  • a web interface (Blazor Server SSR)
  • desktop software that authenticates via an API

The system must allow for:

  1. Manage organisations with multiple users
  2. Allow an organisation to subscribe to one or more products
  3. Support multiple active subscriptions simultaneously, one per product
  4. Allow different plans for the same product (Free / Base / Pro)
  5. Enable or disable individual tools depending on the subscription
  6. Determine quickly and reliably whether an organisation can use a tool
  7. Ensure consistency even in the event of retries, failures, deployments or outbox issues
2. Domain Concepts

2.1 Organization

Represents an engineering firm or practice.

  • It is the functional tenant
  • All subscriptions and permissions are linked to the Organisation, not to individual users

2.2 Product

It is a commercial product sold by the portal.

For instance:

  • GlaSSS
  • ConcreteChecker
  • OSM

Features:

  • This is what is purchased
  • Each product has a dedicated subscription
  • An organisation may have several active subscriptions, but no more than one per product

2.3 Tool

It is a technical feature that can be enabled via the software.

Examples:

  • GlassChecker
  • FeMMM
  • ANT

Features:

  • The software (web or desktop) operates solely at the Tool level
  • It does not recognise Plans or Products
  • It simply asks: “Can I use Tool X?”
  • A Tool belongs to exactly one Product. It is never shared across products, so the product

2.4 Product–Tool Relation (ProductTool)

It defines the product functional catalogue.

This answers the question:

“Which tools are included in this product, regardless of the plans?”

Used for:

  • UI (product catalogue)
  • validation (a plan cannot include tools from another product)
  • roadmap (future tools not yet on sale)

2.5 Plan

It represents a marketing plan for a product.

Features:

  • Each Plan belongs to only one Product
  • It differs in terms of:
  • price per unit
  • number of Seats per unit
  • set of enabled tools
  • usage limits
  • It carries two independent classification attributes:
  • Rank — a pure ordinal placing the plan on its product's commercial ladder
  • CategoryFree, Commercial or Academic. Exactly one plan per product has

Examples:

  • GLASSS_FREE
  • GLASSS_BASE
  • GLASSS_PRO
  • CONCRETE_FREE
  • CONCRETE_BASE
  • CONCRETE_PRO

2.6 Plan–Tool Relation (PlanTool)

It defines the features of the plan.

Answers the question:

“Which tools are included in this plan?”

Reason:

  • Required to distinguish between Free, Base and Pro
  • Not all of the product’s tools are included in every plan

2.7 Subscription

This represents an organisation’s purchased instance of a plan.

Characteristics:

  • It always refers to:
  • Organisation
  • Product
  • Plan
  • It has:
  • quantity purchased
  • number of Seats enabled: Subscription.Seats = Plan.Seats * Subscription.PlanQuantity,
  • int = null -> No Limit. This is a stored, denormalised value (so reading
  • start date
  • end date (or perpetual)
  • status — see Subscription Lifecycle §3 for the full matrix of what each status
  • An organisation may have:
  • multiple active subscriptions
  • no more than one Active subscription for the same Product

Seats are per product. There is no organisation-wide seat limit: an organisation with a
GLASSS subscription of 5 seats and a ConcreteChecker subscription of 2 seats can have up to 5
members enabled for GLASSS and up to 2 enabled for ConcreteChecker.

Access therefore has two independent levels:

  1. a member is activated / deactivated organisation-wide — this is uncapped;
  2. an active member is enabled per product, and this is what consumes a seat.

Deactivating a member organisation-wide disables every product enablement they hold. An active
member may be enabled for any number of products. See Subscription Lifecycle §5.

A Subscription is not a mutable row: it is a chain of period records, where each plan,
quantity or term change closes the current record and opens a linked successor. See
Subscription Lifecycle §2.

2.8 OrganizationToolEntitlement (Entitlement)

It represents actual and verifiable authorisation.

It answers the key question:

“Can this organisation use this tool at this time?”

Characteristics:

  • It is materialised
  • It is derived from subscriptions
  • It contains:
  • OrganisationId
  • ToolId
  • SubscriptionId
  • ValidFrom / ValidUntil
  • IsActive
  • It is the only point of reference for the licensing software

Reasons for implementation:

  • Extremely fast checks
  • No business logic at runtime
  • Support for future add-ons

Entitlements are purely derived and are never authored by hand. Administrators act on
subscriptions (plan, quantity, expiration) and entitlements follow, which is what makes the
delete-and-rebuild strategy safe. Trials are not extra entitlement rows either — they are a flag
on the subscription record (see Subscription Lifecycle §11).

/ SearchD DarkEsc Clear