npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@geonosis/policy

v3.0.0

Published

A threshold is a value plus the authority that set it, the subject it reaches and the reason it exists. The precedence lattice, the rule → config → constant read with its fallback journalled once per boot, the learning loop, the generated policy prose, an

Readme

@geonosis/policy

A threshold is not a number. It is a number, plus the authority that set it, the subject it reaches and the reason it exists — and that difference is what lets the person who was just blocked learn something instead of filing a ticket.

That sentence is true of two tiers, and the earlier version of this README claimed only the first, which is why one consumer read the whole package as not applicable and was right to.

| tier | the question it answers | what it costs | |---|---|---| | runtime — definePolicy / readPolicy | what does this tenant, in this region, for this order get? | a store behind three ports, a boot, and an await at every read | | compile-time — declareThreshold | on whose authority is this number 3000? | one call, no ports, no store, no async, no override |

Most thresholds are the second question. LIVENESS_TIMEOUT_MS = 3000 decides behaviour in code and will never be tenant-settable; what it lacks is not a lattice, it is an authority. Putting it behind the runtime tier would have cost a port and an await to answer a question nobody was asking, and that is precisely why it stayed a magic number.

The runtime half is the kernel two repos arrived at independently: a precedence lattice with a full trace, a read that resolves authored rule → config row → the caller's own constant and RECORDS the third case, the learning loop that reads those recordings back, and a permission lattice with the runtime lifted out of it.

import { definePolicy, readPolicy } from '@geonosis/policy'

const policy = definePolicy({
  tiers: [
    'regulatory',
    'contract',
    { name: 'tenant', overridable: true },
    { name: 'command', overrides: true },
    { name: 'learned', advisory: true },
  ],
  kinds: [{ kind: 'quoteExpiryDays', schema: z.number().positive() }],
  scopeKeys: ['region', 'customerGroup', 'companyId', 'orderId'], // VAGUEST first
})

const { value, usedFallback } = await readPolicy(policy, 'quoteExpiryDays', { companyId }, {
  fallback: DEFAULT_QUOTE_EXPIRY_DAYS,
  rule,
  config,
  journal,
  op: 'create-quote',
})

The kernel is inert until the data arrives. Not one tier, kind, scope key or rule is built in: the two consumers disagreed on every one of them — one's strongest authority is regulatory, the other's is physics, and they share not a single scope key — so all four are declared. A policy with no rules decides nothing, every read falls through to the caller's constant, and each of those is recorded exactly once per boot: the honest unit of evidence for "nobody has set this knob" is a deployment, not a request, and a constraint read once per cart would otherwise write a row per cart and drown the one signal anybody is looking for.

What is in it

| Export | What it does | |---|---| | definePolicy({ tiers, kinds, scopeKeys, rules }) | The lattice as data. Refuses two escape hatches, a duplicate tier or kind, and an advisory tier declared stronger than an authority. | | policy.resolve(kind, query, rules) | The decision plus the whole trace: winner, suppressed, overrode, conflicts, explain. | | policy.unusableRules() · unsupportedScopes() · unsetKinds() | The three honesty reports. A rule this build cannot honour is NAMED, never silently dropped; a kind a reader asks for that no rule sets is named too, because a reader falling back forever looks identical to one that is working. | | readPolicy(policy, kind, scope, opts) | rule → config → constant, through injected rule / config / journal ports. | | policyOrDefault(policy, input, apply) | A resolved value that cannot be APPLIED is the same kind of gap: recorded, and the default takes over. A default that also fails still throws — that is our bug, not a misconfiguration. | | generatePolicyMarkdown · describePolicy | The policy as committed prose, and as the bounded instructions an agent gets at connect. Every count and the precedence sentence are derived. | | observeJournal / reflect / curate / promote / demote / playbookRules | The learning loop. A promoted learning enters at whatever tier the policy calls advisory, so it can only ever fill silence. | | journalRowForEvent | The other three signals' missing input: real lifecycle events as countable rows. | | rulesToSeed(seed, existing) | Seeding idempotent by id AND by coverage. | | runPolicyAdapterConformance(harness) | The suite every storage adapter passes, answering with a report rather than an exit code. | | declareThreshold({ value, authority, reason, subject?, revisit? }) | The compile-time tier. Frozen, so there is no runtime override; refused at the declaration — which is module load — when the authority, the reason or the value is missing, or the revisit is not an ISO date. | | expiredThresholds(list, now) · describeThreshold · isThreshold | A revisit that has passed is REPORTED, never thrown: a build that started failing on a date is a build that gets its date deleted. | | @geonosis/policy/permissions | definePolicies / hasPermission / resolvePermissions / checkPermissions / createPolicyCatalog / expandPolicies. | | @geonosis/policy/medusa · /drizzle | Two stores behind the same ports. Neither imports the store it adapts. |

Migrating a Medusa storefront's rules engine, in five lines

  1. lib/rules.ts → definePolicy({ tiers: POLICY_TIERS, kinds: …, scopeKeys: … }); the twelve PolicyConstraint members become twelve { kind, schema }, and KNOWN_SCOPE_KEYS + scopeSpecificity both disappear into scopeKeys (vaguest first — the weight is the position).
  2. lib/read-policy.ts → readPolicy(policy, kind, query, { fallback, …adapter }); the SLA tier dereference becomes isReference + dereference on the approvalSlaHours kind.
  3. lib/config-store-binding.ts → createMedusaPolicyAdapter({ container, moduleKey, bindings }) with configRow(namespace, key); drop positive() from every binding — the kind's schema now refuses junk once, for the rule layer too.
  4. lib/learning.ts → the same functions; playbookRules(policy, playbook) takes the policy, and journalRowForEvent(name, data, { subjectKeys, actorKeys }) takes the fifteen event names' keys.
  5. modules/rules-engine/service.ts keeps MedusaService and its three models, and loses the mapping: listActiveRules() is the adapter's rule.rules(), and resolve() is policy.resolve.

proofs/022-W7-parity/ lists every one of its 65 kernel cases against this package, the ten that stay consumer-side, and the seven behaviours that deliberately differ.

A threshold without an authority is a gate

{ "packs": [{ "pack": "thresholds", "options": { "sourceRoots": ["packages", "apps"] } }] }

@geonosis/verify-arch's thresholds pack, two checks:

  • T1.1 — a module-scope const whose name is threshold-shaped (_MS, _LIMIT, MAX_, _TTL, _SECONDS, …) and whose value is a bare number. It is a number that decides behaviour and can say only "me, an hour ago" when asked why.
  • T1.2 — one such name declared with two different values in two files. That is the half no per-file linter can reach: grep finds both, and only something holding the whole graph can say they disagree.

The name shapes are a default rather than an empty list, for the reason rails defaults its threat classes and not its caps.auth: _MS and MAX_ are the units and bounds a threshold is spelled in, and none of them is one repo's word for one repo's thing. A repo adds its own with names, excuses one with allow, and names its own wrapper with helper.

A bound declared inside a function is left alone — it is a step in an algorithm, not a repo-wide decision — and the anchor that does that is column zero.

a Workers + D1 app, corrected

The earlier version of this section read: "Its thresholds are lint-enforced constants … They are not [policy]. grep -E '_LIMIT|_THRESHOLD|MAX_|_CAP' across all 34 [constants.ts files] returns nothing." Both halves need correcting.

The grep was over the wrong denominator. It searched the 34 constants.ts files, and the fixture is not in one: LIVENESS_TIMEOUT_MS = 3000 lives in apps/api/src/lib/health-status.ts, module-private, three lines above its only use. Run over the whole of packages/ and apps/ on 2026-09-02, the pack finds seven, and the four cache TTLs that section listed as not policy are among them:

packages/db/src/constants.ts:6      PLACEMENT_CACHE_SECONDS = 300
packages/db/src/constants.ts:7      PLACEMENT_HOT_READ_SECONDS = 30
packages/auth/src/constants.ts:10   PRINCIPAL_HOT_READ_SECONDS = 30
apps/web/features/document/lib/history-stack.ts:1   MAX_PAST = 100
apps/edge/src/constants.ts:5        API_KEY_CACHE_SECONDS = 300
apps/edge/src/constants.ts:9        UNKNOWN_KEY_CACHE_SECONDS = 60
apps/api/src/lib/health-status.ts:8 LIVENESS_TIMEOUT_MS = 3000

And "not policy" was the wrong conclusion from the right observation. The observation — none of them carries an authority, a subject or a reason — is exactly what separates a policy rule from a constant, and the answer to it is the compile-time tier, not the runtime one. §13.3 is a law about WHERE a constant lives; declareThreshold is about who said so. Seven declarations, no store, no port, no await.

What that repo could still adopt on the runtime side, without changing a line of behaviour, is the shape of the call — its constant passed as fallback, so the gap becomes countable — and that is worth precisely as much as its journal is fed, which today is not at all.

D-027 status: one consumer with pull. C3 of docs/challenge-2026-08-30.md ranked this behind @geonosis/integrations for that reason and it was right to; this package ships inside 1.0.0 with a Medusa storefront's kernel as its only live consumer and musa's lattice as a second fixture, not a second consumer. It is DONE when a Medusa storefront depends on the published version and has deleted its lib/.

What it deliberately does NOT do

  • No global registry. Upstream's definePolicies writes into three globalThis objects keyed by name with no duplicate check, and rewrites the caller's objects in place. createPolicyCatalog is local and refuses a name already taken.
  • No store. Rules, config rows and journal entries all arrive through ports. That is what lets every check in the conformance suite run without a booted server.
  • No opinion about your tiers. Including the one that looks universal: whether an unmarked rule may be overridden is overridableByDefault, because the two consumers answer it oppositely.

Consumable from CommonJS

A Medusa backend is module: Node16 CommonJS by upstream requirement, not by preference. This package ships both builds and a require condition carrying its own .d.cts, so a static import type-checks and require() works:

import { definePolicy } from '@geonosis/policy'      // ESM, module: Node16 or ESNext
const { definePolicy } = require('@geonosis/policy') // CommonJS

An ESM-only package is a wall for such a backend, and no amount of parity gets over it: a Medusa storefront measured @geonosis/testbed at 15/15 identical and still could not adopt it, because a static import is TS1479 and await import() cannot serve the synchronous describe() registration its 107 suites are built on.