Skip to content

Releases: Wilkes-Liberty/file_gate

1.10.1

Choose a tag to compare

@jmcerda jmcerda released this 19 Sep 17:06
92af187

[1.10.1] - 2026-09-19

Fixed

  • Revoke takes the same file_gate_redemption:<jti> lock that
    SignedUrl::consumeUse() holds. Without it, a redemption that read the
    counter before the kill mark was written could overwrite the mark and leave
    uses. If the lock cannot be taken, revoke fails: the HTTP routes answer 503
    with Retry-After, and the MCP revoke tool returns its fixed refusal.
    Uninstall also deletes the kill-mark expiry collection.
    #3624474

File Gate 1.10.0

Choose a tag to compare

@jmcerda jmcerda released this 19 Sep 09:21
cf7486c

Added

  • Optional file_gate_mcp submodule: five Tool API plugins governed by MCP
    Sentinel. file_gate_status, file_gate_file_gate, file_gate_grants_list
    and file_gate_metrics are read-only; file_gate_grant_revoke revokes one
    grant and refuses a grant id recorded against another field. No tool returns
    secret material, a file path, a URL or a grant token. The base module's
    dependencies are unchanged, and neither package is in require-dev: MCP
    Sentinel cannot install on Drupal 12, so the submodule's tests skip when the
    two are absent. The submodule requires Tool API and MCP Sentinel
    and declares Drupal ^11.4 only, because MCP Sentinel does not declare
    Drupal 12 yet.
    #3624444
  • file_gate.gated_field_overview service (GatedFieldOverview::fields())
    lists gated fields with their method and storage scheme. The settings form
    now reads from it, so the form and the status tool describe the same set.

Fixed

  • A field storage marked gated on a file scheme other than private is now
    refused at save, on every write path. It was refused only by the field form
    and at configuration import, so the entity API, a recipe, an update hook,
    drush config:set or a configuration tool could write it, and the files
    stayed public. An entity save throws GatedPublicSchemeException before
    anything is written. A raw configuration write is put back and then throws,
    because core has no event before it. The configuration schema carries the
    same rule as the FileGateGatedFieldScheme constraint. A site already in
    this state can still load, edit and re-save the field unchanged, and stays
    an error on the status report; only a save that creates the combination or
    moves it to another non-private scheme is refused. In the field form,
    removing gating and choosing the public scheme in one submit still works,
    and a public field that already holds files still cannot be gated. Each
    refusal is recorded as a field_gating_refused audit event when
    audit_chain is installed.
    #3624449
  • The two status report findings (gated fields on a public file system, and
    named secrets with no field scope) move from hook_requirements() to
    hook_runtime_requirements(). Drupal 13 stops calling the procedural hook,
    and nothing fails when it does: both findings would have left the status
    report without an error. Same keys, titles, severity and text. Removes the
    Drupal 11.3 deprecation notice for file_gate_requirements. Rebuild
    caches after updating (drush updatedb or drush cr): the compiled
    container still lists the removed function until it is rebuilt.
    #3624429
  • A revoked signed_url grant could be redeemed again when it outlived its kill
    mark. Revoke wrote the mark for 30 days, or for the caller's ttl, and
    removed the grant from the inventory list. A grant with a longer life became
    redeemable once the mark lapsed, with nothing left to show it. The mark now
    lasts until the grant's stored expiry plus one hour. A caller ttl can
    lengthen it and cannot shorten it below that. A revoke for a grant with no
    inventory record keeps the 30-day default. Revoking the same grant again
    never shortens the mark the first revoke left. Single and bulk revoke share
    the rule. No API change.
    #3624450

Changed

  • file_gate_requirements() is removed. It was a hook implementation, not an
    API; code that called it should invoke runtime_requirements through the
    module handler. The tests now do, and assert the implementation exists,
    so they fail if the hook stops running.

File Gate 1.9.2

Choose a tag to compare

@jmcerda jmcerda released this 18 Sep 21:09
5f61d53

Fixed

  • Single-jti revoke is field-scoped. POST /api/file-gate/revoke with
    {"jti":"…"} now loads Grant Inventory meta and requires allowsField()
    (plus matching k for a named secret) before spend/forget — the same
    privilege model as token revoke, grant list, and bulk revoke. Out-of-scope
    credentials receive 403; missing meta is 404 so a foreign jti is not
    confirmed and is not spent.

1.9.1

Choose a tag to compare

@jmcerda jmcerda released this 16 Sep 17:47
0e14fc6

Fixed

  • Single-jti revoke now drops grant inventory. POST /api/file-gate/revoke
    with {"jti":"…"} spent the grant but left it listed on
    GET /api/file-gate/grants until natural expiry. Both revoke paths now
    share one GrantInventory::revokeJti() helper that writes the spent
    counter and forget()s the row. The default kill-mark TTL is 30 days on
    both paths (single-jti was 24 hours).

1.9.0

Choose a tag to compare

@jmcerda jmcerda released this 15 Sep 13:13
31d3281

Removed

  • Dead public helpers on the mint/OTP/assurance path. FileGateAudit::isAvailable(), OtpSession::boundEmail(), SessionOidcToken::isAvailable(), and SessionBridge::clearCookie() had no callers. OTP grants() no longer reads a POST body for email/otp — the download route is GET-only; query and FG_OTP cookie redeem are unchanged.

Changed

  • Mint and OTP share one FileTargetResolver for file UUID, media UUID, and unpublished-host resolution.
  • SignedUrl and Token share one resourceId() helper. The HMAC binding (<uuid>|<normalized-uri>) is unchanged.
  • Grant inventory reads the secret id via SecretRegistryInterface::REQUEST_ATTR_SECRET_ID.
  • Maintainer author homepage now points at the drupal.org profile.

1.8.0

Choose a tag to compare

@jmcerda jmcerda released this 27 Aug 17:55
bdaff48

Fixed

  • A field-settings form save no longer strips require_identity_mint on non-assurance methods (d.o #3619534). The setting is enforced by the mint controller for every gate method, but only assurance exposed it — signed_url and token rebuilt their settings from their own form values, so a config-imported require_identity_mint: true was silently removed by any editor pressing Save on the field configuration form, downgrading identity-bound grants to unbound signed URLs with nothing logged. Every mintable method (signed_url, token, and by inheritance referrer_lock) now exposes the checkbox and round-trips the value; assurance inherits the control instead of duplicating it.
  • The grants inventory routes honour the configured flood settings (d.o #3619535). GrantInventoryController read mint_flood_limit/mint_flood_window — keys that do not exist in the schema — so every configured value was silently ignored in favour of the hard-coded 50/60 fallback. Both inventory routes now read flood_limit/flood_window, the same keys the mint route applies.

1.7.0

Choose a tag to compare

@jmcerda jmcerda released this 21 Aug 01:05
ffe901f

Added

  • Identity-aware mint: User hosts, field view, nested parents (d.o #3618403). Acting-account mint now requires (1) file download access, (2) view access on every referencing host, (3) view access on the referencing field (so a field-level deny is not skipped), and (4) view access on each getParentEntity() ancestor when the usage host is a child (paragraph / inline). A gated file with no resolvable host is refused. Kernel coverage for a user host (own vs other) and for a field-view deny; unit coverage for the parent walker.

1.6.1

Choose a tag to compare

@jmcerda jmcerda released this 03 Aug 19:59
fb40819

Changed

  • Friendlier response for a dead download link (#66). A denied gated download (expired, spent, or tampered grant) renders a plain, themeless 403 on the download route instead of Drupal's active-theme access-denied page — which, for a signed-in staff member, was the full admin chrome and read as a fault rather than an expired link. Still a 403, still discloses no grant state, and a dead link is still never offered step-up. Implemented as a scoped exception subscriber, so the controller's deny contract and its security logging are unchanged.

1.6.0

Choose a tag to compare

@jmcerda jmcerda released this 03 Aug 17:06
c8fe1b7

Added

  • Multi-issuer assurance (#60 / d.o #3614673): the assurance method accepts a trusted_issuers list — each entry with its own issuer, audience, and accepted acr values. A token matches exactly one entry by iss; no cross-matching, no fallback, unknown issuers denied without any discovery traffic. The legacy single-issuer settings keep working as a one-entry list.
  • Site-relative step_up_login_url (#62 / d.o #3614675): a single-slash relative path is accepted alongside absolute http(s), keeping exported config environment-neutral when the site provides its own step-up initiator route.

Changed

  • Clearing a managed assurance setting in the field form now actually clears it (previously the stale stored value silently survived).

Fixed

  • Step-up page validates the stored token shape before building the Authorization header (#53 / d.o #3614534) — malformed tokens get an actionable message instead of a cryptic fetch TypeError.

File Gate 1.5.2

Choose a tag to compare

@jmcerda jmcerda released this 02 Aug 22:25

Fixed

  • Assurance token endpoints beside simple_oauth, correctly this time (#56 / d.o #3614535). The 1.5.1 _auth route pin is inert for this failure: global authentication providers authenticate before routing. A new AuthorizationShield http middleware stashes the Bearer/DPoP Authorization value into a request attribute and removes the header on File Gate's own token endpoints before any provider runs; handlers read the stash transparently. Standard wire semantics preserved; no client changes.

No update functions; no configuration or API changes. Safe drop-in update from 1.5.0/1.5.1. Sites running simple_oauth should update immediately — the assurance token redeem path does not work without this.

drupal.org release: https://www.drupal.org/project/file_gate/releases/1.5.2