| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| AccessControl v3.1.0 source code.tar.gz | 2026-07-16 | 321.0 kB | |
| AccessControl v3.1.0 source code.zip | 2026-07-16 | 375.1 kB | |
| README.md | 2026-07-16 | 3.4 kB | |
| Totals: 3 Items | 699.5 kB | 1 | |
Added
- Temporal schedules — the
duringcondition operator. Grants (andrequire()gates) can now be constrained to real schedules — recurrences, calendar ranges, unions of windows — via dtrexp expressions:.where('$.now during "T0900:1800 E1:5"')means weekdays, 09:00–18:00. Joinsbefore/after/betweenin the Time operator family; works in string sugar, canonical JSON, combinators, gates, and on both the sync and async check paths. .during(expression)chainer on grants — fluent shorthand that ANDs a['$.now', 'during', …]leaf into the grant's condition at commit; composes with.where()regardless of call order, and repeated calls AND together.- Any date-like left side. Beyond
$.now, the checked instant can come from context data ('$.booking.start during "…"') as aDate, epoch milliseconds, ISO string, or{ epochMilliseconds }object. A non-date-like value evaluates false (fail-closed), never throws at check time. $.now.epochMilliseconds— the raw instant, now part of the derived$.now.*fields.- The
out_of_scheduledeny reason + publicpermission.reason. When a check fails only because of aduringschedule — it would be granted at a covered instant — the reason is'out_of_schedule'instead of the generic'condition_failed'/'require_failed', so a UI can say "outside your access hours" and mean it ("granted, but not now"). If a value predicate also failed, the generic reason stands. The denial reason (previously event-only) is now also exposed as a publicreasongetter onPermission. - Error codes
INVALID_DTREXPandDTREXP_NEVER_MATCHES. Expressions are validated at every grants entry point (chainer commit, constructor,setGrants, grants-list,require(),restore()): malformed ones throw with dtrexp's message and character position; parseable-but-never-matching ones (D30 M2) are rejected as authoring bugs.
Security
- The
duringsurface is bounded like the rest of the condition DSL: expression length cap (1000 chars), commit-time validation, and a bounded FIFO parse cache — untrusted serialized grants can't reach the check path unvalidated or grow memory through distinct expression strings. - Timezone comes from the reserved
context.tz(IANA name), the same key$.now.*uses; with notz, both evaluate in the system zone — one timezone story across the condition system.
Changed
AccessReasonis nowDenyReason. The type only ever describes a denial (undefinedwhen granted), so it's named for what it is.AccessReasonremains exported as a deprecated alias — existing imports keep compiling — and will be removed in v4.
Dependencies
- Added
dtrexp1.0.1(exactly pinned, same author, zero transitive dependencies). Engines unchanged (Node ≥ 20).
Tooling
- CI now enforces the full quality bar. The workflow runs
typecheck → lint → build → coveracross the Node 20/22/24 matrix and a dedicated mutation job (Stryker, on Node 24) — so 100% coverage and the mutation threshold are gated on every push and PR, not justbuild+test. - CI pins
TZ=Europe/Istanbulso system-timezone default paths stay distinguishable from UTC in tests and mutation runs.