atlas_rb 1.8.5 → 1.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b34244827cff750075d39c45f1fd628840b6b1637a06f6bfefc876f285eafbe
4
- data.tar.gz: d3f429989a1b983ed13a39c8363b17f1eff439d829f3694244327a38cfc2ca7e
3
+ metadata.gz: 88e591bc06be2edcf972e7df8490f57656f0562680d3546598f7461b1ad25bc3
4
+ data.tar.gz: 997084c70c482d78cbc4627d7dcf65b91a1687b8bf6ed1855c0f46613b007389
5
5
  SHA512:
6
- metadata.gz: 70c4cce5eacaabca34495bee0cd8ed0ada54998e7a90f3b39b26b601d4d20be9e16355d64ac68e75fe39fce8f28d3e25e275d5627afd3644e296c18fdca3453e
7
- data.tar.gz: b46212f70bfbec6a343654f89e73e33a13a372abb2e42ff0bf88a0a667d2d5033cee6e221dbdc63022b9feca6f0fd7000c12eb90172a76feaa11540696c04daa
6
+ metadata.gz: 87d74362da0a1b9fe6655c675fe834dce9c1ea824012d9f482c1828fbe6f299495793836c6840528d350aad020a1a28bf3a53f52136c336c114a3e41afb61096
7
+ data.tar.gz: b02aac392fa82e3f64c5a391e23215aa2eb6577285ddb0517ac2653ae67f33603dc05e4af018acb73c5a2d9859fc2b137309f51525db6b40aa36897cbe957cfa
data/.version CHANGED
@@ -1 +1 @@
1
- 1.8.5
1
+ 1.8.7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.8.7
4
+
5
+ ### Added — personal-access token lifecycle (`System::Token.mint` / `.revoke`)
6
+
7
+ New system-context binding for the `POST /nuid` / `DELETE /nuid` endpoints so a
8
+ host app can mint and revoke a user's personal-access JWT (`ATLAS_JWT`, BYO-JWT
9
+ mode). Both are :system-gated on Atlas ("minting for an arbitrary NUID is
10
+ 'become anyone'"), so they authenticate via `FaradayHelper#system_connection`
11
+ (hard-pinned system token + `User: NUID` header) — never the ambient-user
12
+ relay-signing path — mirroring `System::User`.
13
+
14
+ - `AtlasRb::System::Token.mint(nuid:)` → the JWT (`String`), or `nil` when the
15
+ NUID has no Atlas User row (404). The token is full-privilege for that user,
16
+ 1-week TTL, single-jti.
17
+ - `AtlasRb::System::Token.revoke(nuid:)` → `true` on success (204), `false` on
18
+ 404. Rotates the user's jti (single-jti model → all outstanding tokens die at
19
+ once). "Regenerate" is `revoke` followed by a fresh `mint`.
20
+
21
+ Unblocks Cerberus's "My DRS → Programmatic access" section (generate / regenerate
22
+ / revoke), gated to the `northeastern:drs:repository:api` Grouper group.
23
+
3
24
  ## 1.8.5
4
25
 
5
26
  ### Fixed — `find` returns a tombstone (`410`) instead of raising
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- atlas_rb (1.8.5)
4
+ atlas_rb (1.8.7)
5
5
  faraday (~> 2.7)
6
6
  faraday-follow_redirects (~> 0.3.0)
7
7
  faraday-multipart (~> 1)
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AtlasRb
4
+ module System
5
+ # Personal-access token lifecycle — mint and revoke the 1-week JWT a real
6
+ # person exports as `ATLAS_JWT` to drive atlas_rb / curl against Atlas
7
+ # headless (BYO-JWT mode, see {AtlasRb::FaradayHelper}). Cerberus's "My DRS
8
+ # → Programmatic access" section calls these post-SSO and hands the token
9
+ # to the librarian; the token is never persisted by Cerberus.
10
+ #
11
+ # ## Why a separate class from {System::User}
12
+ #
13
+ # Token lifecycle is a distinct concern from SSO user provisioning: minting
14
+ # a bearer credential for someone is "become anyone," which is exactly why
15
+ # both Atlas endpoints are :system-gated (`authorize! :mint_token, User`).
16
+ # Keeping it in its own class keeps that carve-out legible rather than
17
+ # burying it among provisioning methods.
18
+ #
19
+ # Both methods authenticate via {FaradayHelper#system_connection} — the
20
+ # hard-pinned system token + `User: NUID` header — so there is no way to
21
+ # issue them as a regular user. This is never the ambient-user
22
+ # relay-signing path.
23
+ class Token
24
+ extend AtlasRb::FaradayHelper
25
+
26
+ # Mint a personal-access JWT for a real person (`POST /nuid`).
27
+ # System-gated. The returned token authenticates as `nuid` in BYO-JWT
28
+ # mode (Atlas resolves identity from the token's `sub`, ignores any
29
+ # `User:` / `On-Behalf-Of` header, and refuses `:system`/`:anonymous`).
30
+ # Full-privilege for that user, 1-week TTL, single-jti.
31
+ #
32
+ # @param nuid [String] the NUID the token will act as.
33
+ # @return [String, nil] the JWT, or nil when the NUID has no Atlas User
34
+ # row (404) — a clean "no such user" signal for the caller to surface.
35
+ def self.mint(nuid:)
36
+ response = system_connection.post("/nuid", { nuid: nuid }.to_json)
37
+ return nil if response.status == 404
38
+
39
+ AtlasRb::Mash.new(JSON.parse(response.body))["token"]
40
+ end
41
+
42
+ # Revoke every outstanding token for a user (`DELETE /nuid`) by rotating
43
+ # its jti. System-gated. Single-jti model → all-or-nothing: every token
44
+ # the user holds dies at once. "Regenerate" on the Cerberus side is
45
+ # {.revoke} followed by a fresh {.mint}.
46
+ #
47
+ # The NUID rides as a query param (`system_connection`'s params hash) so
48
+ # this sidesteps DELETE-with-body handling; Atlas reads it from
49
+ # `params[:nuid]` either way.
50
+ #
51
+ # @param nuid [String] the NUID whose tokens to invalidate.
52
+ # @return [Boolean] true on success (204), false when the NUID has no
53
+ # Atlas User row (404).
54
+ def self.revoke(nuid:)
55
+ system_connection({ nuid: nuid }).delete("/nuid").status == 204
56
+ end
57
+ end
58
+ end
59
+ end
data/lib/atlas_rb/work.rb CHANGED
@@ -345,28 +345,37 @@ module AtlasRb
345
345
  ))
346
346
  end
347
347
 
348
- # Replace a Work's per-tier derivative-visibility policy.
348
+ # Replace a Work's per-asset derivative-visibility policy.
349
349
  #
350
- # Sets which read groups may fetch the Work's sized image derivatives —
351
- # the `small` / `medium` / `large` / `service` (deep-zoom) tiers — reusing
352
- # the resource read-group vocabulary (`"public"`, Grouper group names,
353
- # `[]` = private). Unlike {.set_image_derivatives} (which upserts URIs) this
354
- # is a whole-object REPLACE: the map you pass is the complete policy;
355
- # omitted tiers inherit by cascade (an absent tier inherits the next
356
- # lower-resolution tier; `small` inherits the Work's own visibility). Pass a
357
- # tier as `[]` to make it private.
350
+ # Sets which read groups may fetch each of the Work's downloadable
351
+ # renditions, reusing the resource read-group vocabulary (`"public"`,
352
+ # Grouper group names, `[]` = private). Two media families:
353
+ #
354
+ # * the image ladder `small` / `medium` / `large` / `service` (deep-zoom) /
355
+ # `master` (the original image), and
356
+ # * independent media `audio` / `video` / `pdf`.
358
357
  #
359
- # Atlas enforces two invariants: a tier may not be more visible than the
360
- # Work, and visibility must narrow as resolution grows
361
- # (`service` `large` `medium` `small`). The gate is advisory — it
362
- # surfaces per Delegate on {.assets} as `gated` / `permission` for the
363
- # display layer (Cerberus / the IIIF auth service) to enforce.
358
+ # Unlike {.set_image_derivatives} (which upserts URIs) this is a whole-object
359
+ # REPLACE: the map you pass is the complete policy. Within the image ladder
360
+ # omitted tiers inherit by cascade (an absent tier inherits the next
361
+ # lower-resolution tier; `small` inherits the Work's own visibility).
362
+ # Independent media do NOT cascade an absent `audio`/`video`/`pdf` key
363
+ # rides the Work. Pass a tier as `[]` to make it private.
364
+ #
365
+ # Atlas enforces: a tier may not be more visible than the Work, and — within
366
+ # the image ladder — visibility must narrow as resolution grows
367
+ # (`master` ⊆ `service` ⊆ `large` ⊆ `medium` ⊆ `small`; independent media
368
+ # impose no ordering). The gate is advisory — it surfaces on {.assets} as
369
+ # `gated` / `permission` for BOTH Delegate (image tier) and Blob (master /
370
+ # pdf / audio / video, classified by media type) entries, for the display
371
+ # layer (Cerberus / the IIIF auth service; Cerberus's download :read check)
372
+ # to enforce.
364
373
  #
365
374
  # @param id [String] the Work ID.
366
375
  # @param policy [Hash] tier => Array(read groups), e.g.
367
- # `{ large: ["northeastern:drs:repository:archives"], service: [...] }`.
368
- # Keys may be strings or symbols; only `small` / `medium` / `large` /
369
- # `service` are recognized.
376
+ # `{ large: ["northeastern:drs:repository:archives"], master: [...] }`.
377
+ # Keys may be strings or symbols; recognized keys are `small` / `medium` /
378
+ # `large` / `service` / `master` / `audio` / `video` / `pdf`.
370
379
  # @param nuid [String, nil] optional acting user's NUID. On the relay-signing
371
380
  # path it is signed into the assertion `sub`; on the BYO-JWT (`ATLAS_JWT`)
372
381
  # path it is ignored (identity lives in the token).
@@ -437,6 +446,11 @@ module AtlasRb
437
446
  # duck-type on the field they need rather than expecting a single
438
447
  # schema.
439
448
  #
449
+ # Every entry (Blob and Delegate) also carries the advisory read gate set
450
+ # via {.set_derivative_permissions}: `gated` (true if the asset must be
451
+ # authorized rather than fetched directly) and `permission` (the effective
452
+ # read-group set, or `nil` for guests, to whom group names are withheld).
453
+ #
440
454
  # @param id [String] the Work ID.
441
455
  # @param nuid [String, nil] optional acting user's NUID. On the relay-signing
442
456
  # path it is signed into the assertion `sub`; on the BYO-JWT (`ATLAS_JWT`)
data/lib/atlas_rb.rb CHANGED
@@ -30,6 +30,7 @@ require_relative "atlas_rb/admin/collection"
30
30
  require_relative "atlas_rb/admin/community"
31
31
  require_relative "atlas_rb/system"
32
32
  require_relative "atlas_rb/system/user"
33
+ require_relative "atlas_rb/system/token"
33
34
  require_relative "atlas_rb/audit_event"
34
35
 
35
36
  # Ruby client for the Atlas API — Northeastern University's institutional
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atlas_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.5
4
+ version: 1.8.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cliff
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-02 00:00:00.000000000 Z
11
+ date: 2026-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -150,6 +150,7 @@ files:
150
150
  - lib/atlas_rb/person.rb
151
151
  - lib/atlas_rb/resource.rb
152
152
  - lib/atlas_rb/system.rb
153
+ - lib/atlas_rb/system/token.rb
153
154
  - lib/atlas_rb/system/user.rb
154
155
  - lib/atlas_rb/user.rb
155
156
  - lib/atlas_rb/version.rb