atlas_rb 1.3.6 → 1.3.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: e15c24fddbec1fba3da8aef5e85d769ddf4861e9bccad136957b342515e34dab
4
- data.tar.gz: 2044a925120234a5e3fa1553fc3fc4ec2b3dad05c4215af58697c157fc84cdff
3
+ metadata.gz: 2edc49cf965b1b1489e639b3ae8fd0413d036fe81b07a83c48f851ed975da1a0
4
+ data.tar.gz: ba269fae419aa13545e9e5c664e7c1b66282bcb4ff9c8e238d1333e2c51f444e
5
5
  SHA512:
6
- metadata.gz: a62880ec96483584dc82cacd3a186822ec7af2f64893ede345ccc73f071462106f21b753579dcb6eb9c391018860f828881d4fa7cbe191da4f3e8a76b27d6574
7
- data.tar.gz: b4f66124c5b5c51e550a13b3c60a01a4ce9d6efaa771577be41d46d8f4172967d5124441db1a2a55c44717b92898175643c35d74afe550405a5d57a75fe73767
6
+ metadata.gz: 5ed3a6c2f5d1934a25654fd0130e4f8bc8cf41e00530dfee5b333d4e09bdf9caacdd25f88eecb88426bbf9ba3a61f870faf2b9fece2fb13b7a066a24818bf4e8
7
+ data.tar.gz: ea5ddec2aea0f36cfbebc2150035517857beb24a015b19deade470507604d771bd8b9bd50151d8260e425de355bbe7af502e7dd284819207260a5066cad814ff
data/.version CHANGED
@@ -1 +1 @@
1
- 1.3.6
1
+ 1.3.7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- atlas_rb (1.3.6)
4
+ atlas_rb (1.3.7)
5
5
  faraday (~> 2.7)
6
6
  faraday-follow_redirects (~> 0.3.0)
7
7
  faraday-multipart (~> 1)
data/README.md CHANGED
@@ -25,12 +25,13 @@ Then `bundle install`, or install standalone with `gem install atlas_rb`.
25
25
 
26
26
  ### Environment variables
27
27
 
28
- Every regular-path request reads two environment variables:
28
+ Every regular-path request reads these environment variables:
29
29
 
30
30
  | Variable | Purpose |
31
31
  |---------------|---------------------------------------------------------------|
32
32
  | `ATLAS_URL` | Base URL of the Atlas API (e.g. `https://atlas.example.edu`). |
33
- | `ATLAS_TOKEN` | Bearer token used in the `Authorization` header. |
33
+ | `ATLAS_TOKEN` | Cerberus-relay bearer token used in the `Authorization` header (relay mode). |
34
+ | `ATLAS_JWT` | *Optional.* A personal-access JWT minted by Atlas's `POST /nuid`. When set, switches to [BYO-JWT mode](#byo-jwt-mode-standalone-scripts). |
34
35
 
35
36
  ```ruby
36
37
  ENV["ATLAS_URL"] = "https://atlas.example.edu"
@@ -76,6 +77,35 @@ AtlasRb::Work.find("w-789", nuid: "X")
76
77
  If neither the call site nor the registered default supplies a value,
77
78
  no header is sent (legacy bearer-only path preserved).
78
79
 
80
+ ### BYO-JWT mode (standalone scripts)
81
+
82
+ The relay path above is what a Rails host (Cerberus) uses: a shared
83
+ `ATLAS_TOKEN` plus a `User: NUID` header naming the acting person. For
84
+ **standalone scripts** — a librarian automating their own workflow — Atlas
85
+ also accepts a *personal-access JWT*, minted by Cerberus post-SSO via
86
+ `POST /nuid` and handed to the user. Set it as `ATLAS_JWT` and the gem
87
+ switches transport modes:
88
+
89
+ ```ruby
90
+ ENV["ATLAS_URL"] = "https://atlas.example.edu"
91
+ ENV["ATLAS_JWT"] = "<token minted for you by Cerberus>" # 1-week TTL
92
+
93
+ # Identity is carried by the token — no nuid plumbing needed:
94
+ AtlasRb::Work.find("w-789")
95
+ ```
96
+
97
+ In BYO-JWT mode:
98
+
99
+ - The JWT is the bearer, **taking precedence over `ATLAS_TOKEN`**.
100
+ - **No `User:` header is sent** — the token already encodes the acting
101
+ user, and any `nuid:` kwarg or `default_nuid` is ignored on this path.
102
+ - **`On-Behalf-Of` is suppressed** — acting-as is a Cerberus-relay-only
103
+ concept; Atlas rejects it on the JWT path with a 403. Any `on_behalf_of:`
104
+ kwarg or `default_on_behalf_of` is dropped.
105
+
106
+ To rotate or revoke, ask Cerberus to regenerate your token (Atlas rotates
107
+ the user's `jti`, invalidating outstanding tokens — single-token model).
108
+
79
109
  ### System-path credentials
80
110
 
81
111
  Calls under `AtlasRb::System::*` (currently just SSO user provisioning)
@@ -3,18 +3,32 @@
3
3
  module AtlasRb
4
4
  # HTTP transport helpers shared by every resource class.
5
5
  #
6
- # Every Atlas request reads two environment variables:
6
+ # Every Atlas request reads these environment variables:
7
7
  #
8
8
  # - `ATLAS_URL` — base URL of the Atlas API (e.g. `https://atlas.example.edu`).
9
- # - `ATLAS_TOKEN` — bearer token used in the `Authorization` header.
9
+ # - `ATLAS_TOKEN` — Cerberus-relay bearer token used in the `Authorization`
10
+ # header on the default (relay) path.
11
+ # - `ATLAS_JWT` — *optional* personal-access JWT (minted by Atlas's
12
+ # `POST /nuid`, Cerberus-delegated post-SSO). When set, it switches the
13
+ # transport into **bring-your-own-JWT mode** (see below).
10
14
  #
11
- # Most calls also identify the acting user via a `User: NUID <nuid>` header,
12
- # and optionally an `On-Behalf-Of: NUID <nuid>` header for acting-as / view-as
13
- # flows. When `nuid` / `on_behalf_of` are omitted (positional arg `nil`,
14
- # kwarg `nil`), the helper falls through to {AtlasRb.config}'s
15
+ # ## Two transport modes
16
+ #
17
+ # **Relay mode (default, `ATLAS_JWT` unset).** Authenticates with
18
+ # `ATLAS_TOKEN` and identifies the acting user via a `User: NUID <nuid>`
19
+ # header, optionally an `On-Behalf-Of: NUID <nuid>` header for acting-as /
20
+ # view-as flows. When `nuid` / `on_behalf_of` are omitted (positional arg
21
+ # `nil`, kwarg `nil`), the helper falls through to {AtlasRb.config}'s
15
22
  # `default_nuid` / `default_on_behalf_of` callables — host applications wire
16
23
  # those up to their request-scoped `Current.*` source. Caller-passed values
17
- # always win over the configured defaults.
24
+ # always win over the configured defaults. This is the path Cerberus uses.
25
+ #
26
+ # **BYO-JWT mode (`ATLAS_JWT` set).** Authenticates with the JWT, which
27
+ # already encodes the acting user — so **no `User:` header is sent**, and
28
+ # `On-Behalf-Of` is **suppressed** (Atlas rejects acting-as on the JWT path
29
+ # with a 403; acting-as is a relay-only concept). `ATLAS_JWT` takes
30
+ # precedence over `ATLAS_TOKEN`. This is the standalone-script path: a
31
+ # librarian exports their minted token and runs headless against the API.
18
32
  #
19
33
  # The module is mixed in via `extend`, so its methods become class methods on
20
34
  # the host (e.g. `AtlasRb::Work.connection({})`).
@@ -43,15 +57,7 @@ module AtlasRb
43
57
  # @example Fetching a community
44
58
  # AtlasRb::Community.connection({}).get('/communities/abc123')
45
59
  def connection(params, nuid=nil, on_behalf_of: nil, idempotency_key: nil)
46
- nuid ||= AtlasRb.config.default_nuid&.call
47
- on_behalf_of ||= AtlasRb.config.default_on_behalf_of&.call
48
-
49
- headers = {
50
- "Content-Type" => "application/json",
51
- "Authorization" => "Bearer #{ENV.fetch("ATLAS_TOKEN", nil)}"
52
- }
53
- headers["User"] = "NUID #{nuid}" if nuid
54
- headers["On-Behalf-Of"] = "NUID #{on_behalf_of}" if on_behalf_of
60
+ headers = auth_headers(nuid, on_behalf_of).merge("Content-Type" => "application/json")
55
61
  headers["Idempotency-Key"] = idempotency_key if idempotency_key
56
62
 
57
63
  Faraday.new(
@@ -91,14 +97,7 @@ module AtlasRb
91
97
  # }
92
98
  # AtlasRb::Blob.multipart.post('/files/', payload)
93
99
  def multipart(nuid=nil, on_behalf_of: nil, idempotency_key: nil)
94
- nuid ||= AtlasRb.config.default_nuid&.call
95
- on_behalf_of ||= AtlasRb.config.default_on_behalf_of&.call
96
-
97
- headers = {
98
- "Authorization" => "Bearer #{ENV.fetch("ATLAS_TOKEN", nil)}"
99
- }
100
- headers["User"] = "NUID #{nuid}" if nuid
101
- headers["On-Behalf-Of"] = "NUID #{on_behalf_of}" if on_behalf_of
100
+ headers = auth_headers(nuid, on_behalf_of)
102
101
  headers["Idempotency-Key"] = idempotency_key if idempotency_key
103
102
 
104
103
  Faraday.new(
@@ -149,5 +148,33 @@ module AtlasRb
149
148
  f.adapter Faraday.default_adapter
150
149
  end
151
150
  end
151
+
152
+ private
153
+
154
+ # Build the auth + identity headers shared by {#connection} and
155
+ # {#multipart}. BYO-JWT mode (`ATLAS_JWT` set) sends only the bearer — the
156
+ # token carries the acting user, so no `User:` header, and `On-Behalf-Of`
157
+ # is suppressed (Atlas 403s acting-as on the JWT path). Relay mode uses
158
+ # `ATLAS_TOKEN` and names the acting user, falling through to the
159
+ # configured `default_nuid` / `default_on_behalf_of` callables when the
160
+ # caller passes neither.
161
+ def auth_headers(nuid, on_behalf_of)
162
+ jwt = ENV.fetch("ATLAS_JWT", nil)
163
+ return { "Authorization" => "Bearer #{jwt}" } if jwt
164
+
165
+ relay_headers(nuid, on_behalf_of)
166
+ end
167
+
168
+ # Relay-path headers: ATLAS_TOKEN bearer + the acting-user identity headers,
169
+ # falling through to the configured default_nuid / default_on_behalf_of.
170
+ def relay_headers(nuid, on_behalf_of)
171
+ nuid ||= AtlasRb.config.default_nuid&.call
172
+ on_behalf_of ||= AtlasRb.config.default_on_behalf_of&.call
173
+
174
+ headers = { "Authorization" => "Bearer #{ENV.fetch("ATLAS_TOKEN", nil)}" }
175
+ headers["User"] = "NUID #{nuid}" if nuid
176
+ headers["On-Behalf-Of"] = "NUID #{on_behalf_of}" if on_behalf_of
177
+ headers
178
+ end
152
179
  end
153
180
  end
data/lib/atlas_rb.rb CHANGED
@@ -32,10 +32,15 @@ require_relative "atlas_rb/audit_event"
32
32
  #
33
33
  # ## Configuration
34
34
  #
35
- # Two environment variables drive every request:
35
+ # Environment variables drive every request:
36
36
  #
37
37
  # - `ATLAS_URL` — base URL of the Atlas API (e.g. `https://atlas.example.edu`).
38
- # - `ATLAS_TOKEN` — bearer token sent in the `Authorization` header.
38
+ # - `ATLAS_TOKEN` — Cerberus-relay bearer token sent in the `Authorization`
39
+ # header on the default path.
40
+ # - `ATLAS_JWT` — optional personal-access JWT (minted by Atlas's
41
+ # `POST /nuid`). When set, the transport runs in bring-your-own-JWT mode:
42
+ # the JWT is the bearer and no `User:` / `On-Behalf-Of:` headers are sent.
43
+ # See {AtlasRb::FaradayHelper} for the mode semantics.
39
44
  #
40
45
  # {AtlasRb::Authentication} additionally accepts an NUID (Northeastern
41
46
  # University ID) which is forwarded in a `User: NUID <nuid>` header so the
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.3.6
4
+ version: 1.3.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-06-12 00:00:00.000000000 Z
11
+ date: 2026-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday