standard_id 0.52.0 → 0.53.0
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 +4 -4
- data/CHANGELOG.md +41 -4
- data/README.md +48 -5
- data/lib/generators/standard_id/install/install_generator.rb +4 -1
- data/lib/generators/standard_id/install/templates/standard_id.rb +11 -563
- data/lib/generators/standard_id/install/templates/standard_id_reference.rb +581 -0
- data/lib/standard_id/app_environment.rb +26 -0
- data/lib/standard_id/config/schema.rb +9 -9
- data/lib/standard_id/engine.rb +1 -1
- data/lib/standard_id/passwordless/verification_service.rb +4 -4
- data/lib/standard_id/provider_registry.rb +1 -1
- data/lib/standard_id/testing/request_helpers.rb +99 -0
- data/lib/standard_id/version.rb +1 -1
- data/lib/standard_id.rb +1 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1aa1e111cbaf2abc19d4b43e57a7c276054bf0522418c7303f855659cb3c259f
|
|
4
|
+
data.tar.gz: 583e0568a53fbf9880c11cd0fbf4e17ae2b98d73b52b2db2725ed5dbe4a5dab0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d5410924e96b90aca074e3a322cfa7e59fc54c5412e41927157b19f03c723355724295a67cc9ddb3dec70ca38e548c1bf8062431a46859c6ab153c6416f3b9e6
|
|
7
|
+
data.tar.gz: 3216249e86cd957cc0196518374b2b21073ef03f3f134988f97bedc064ecbbbd9e10a7be88a48606ae7502c9b1dcdecbd8fdd606bea9aa81b361269e2cc9cbbc
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.53.0] - 2026-10-22
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`StandardId::Testing::RequestHelpers#sign_in_as(account, scope: nil)`.** Signs an
|
|
15
|
+
account in for the following requests in a request spec: it creates a real
|
|
16
|
+
`BrowserSession` and writes the encrypted `session_token` cookie a real sign-in
|
|
17
|
+
writes, built with the host's own cookie jar, so no test-only route is added to
|
|
18
|
+
the app. `scope:` also writes `standard_id_scopes` into the Rails session cookie
|
|
19
|
+
(cookie session store only; any other store raises `ArgumentError`, before
|
|
20
|
+
anything is created). Like a real sign-in it always replaces the Rails session
|
|
21
|
+
cookie, so a later `sign_in_as` never inherits an earlier one's scopes or any
|
|
22
|
+
other session data (flash, CSRF token). Replaces per-app controller
|
|
23
|
+
stubs and `/test/set-session` routes.
|
|
24
|
+
- **`RequestHelpers#bearer_headers_for(account, **jwt_options)`:** `build_jwt` plus
|
|
25
|
+
`bearer_auth_header` in one call.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **"Production" follows `APP_ENVIRONMENT`, failing closed.** The new
|
|
30
|
+
`StandardId::AppEnvironment.production?` decides every production check in the
|
|
31
|
+
gem: the bypass-code guard (when `passwordless.production_env_detector` is
|
|
32
|
+
unset), the provider-misconfiguration `:raise` mode, and the empty
|
|
33
|
+
`allowed_audiences` boot warning. It reads `APP_ENVIRONMENT` when set (only
|
|
34
|
+
`staging`, `preview`, `development` and `test` are non-production; any other
|
|
35
|
+
value is production), else `Rails.env.production?`. A staging box with
|
|
36
|
+
`RAILS_ENV=production` and `APP_ENVIRONMENT=staging` is therefore no longer
|
|
37
|
+
treated as production, and `-> { AppEnv.production? }` detectors can be
|
|
38
|
+
deleted. Same convention as standard_audit, standard_health and
|
|
39
|
+
standard_singpass.
|
|
40
|
+
- **`rails g standard_id:install` writes a minimal initializer.** It holds only
|
|
41
|
+
`account_class_name`, plus commented `issuer` and `c.preset :inertia_web` lines,
|
|
42
|
+
instead of several hundred lines of commented defaults that apps then kept
|
|
43
|
+
verbatim. `--with-reference` writes
|
|
44
|
+
the annotated initializer as before. Existing initializers are not touched.
|
|
45
|
+
|
|
10
46
|
## [0.52.0] - 2026-10-22
|
|
11
47
|
|
|
12
48
|
### Added
|
|
@@ -14,10 +50,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
14
50
|
- **`c.preset :inertia_web`.** Applies the settings an Inertia app with
|
|
15
51
|
passwordless or social sign-in flips: `use_inertia` and `alias_current_user`
|
|
16
52
|
true; `web.signup`, `web.password_login` and `web.password_reset` false;
|
|
17
|
-
`oauth.discovery_endpoint_base = :request`.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
53
|
+
`oauth.discovery_endpoint_base = :request`. Each setting is hand-set in four
|
|
54
|
+
of the five estate apps, though the full bundle matches only two of them. A
|
|
55
|
+
preset fills only settings the host has not assigned (via
|
|
56
|
+
`Scope#assigned?`), so explicit assignments win in either order; an unknown
|
|
57
|
+
name raises `ArgumentError`. The public defaults are unchanged.
|
|
21
58
|
Presets live in `StandardId::Config::Presets`.
|
|
22
59
|
|
|
23
60
|
## [0.51.2] - 2026-10-21
|
data/README.md
CHANGED
|
@@ -63,6 +63,13 @@ $ bundle install
|
|
|
63
63
|
rails generate standard_id:install
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
This writes a short `config/initializers/standard_id.rb` holding only what an
|
|
67
|
+
app must decide (`account_class_name`, plus commented `issuer` and
|
|
68
|
+
`c.preset :inertia_web` lines). Add a setting only when you change it from the
|
|
69
|
+
default. `--with-reference` writes the annotated initializer instead, with every
|
|
70
|
+
commonly changed setting and its default commented out; it is a reference to
|
|
71
|
+
read, not a file to keep whole.
|
|
72
|
+
|
|
66
73
|
### 2. Configure Your Account Model
|
|
67
74
|
|
|
68
75
|
```ruby
|
|
@@ -869,15 +876,19 @@ end
|
|
|
869
876
|
|
|
870
877
|
**Bypass code (E2E testing).** When `StandardId.config.passwordless.bypass_code` is set (and the deploy is not production), `Otp.verify` accepts the bypass code for **any realm**. This replaces per-app bypass ENV checks and works consistently across `Otp.verify` and the built-in passwordless login flow. Never set `bypass_code` in production — it will raise if you try.
|
|
871
878
|
|
|
872
|
-
|
|
879
|
+
"Production" is decided by `StandardId::AppEnvironment`, the same rule every
|
|
880
|
+
check in the gem uses: `APP_ENVIRONMENT` when it is set, where only `staging`,
|
|
881
|
+
`preview`, `development` and `test` count as non-production (any other value,
|
|
882
|
+
including a typo, is production), else `Rails.env.production?`. So a staging box
|
|
883
|
+
running `RAILS_ENV=production` with `APP_ENVIRONMENT=staging` is not
|
|
884
|
+
production, and needs no extra wiring:
|
|
873
885
|
|
|
874
886
|
```ruby
|
|
875
|
-
|
|
876
|
-
c.passwordless.production_env_detector = -> { AppEnv.production? }
|
|
877
|
-
c.passwordless.bypass_code = ENV["STANDARD_ID_BYPASS_CODE"] unless AppEnv.production?
|
|
887
|
+
c.passwordless.bypass_code = ENV["STANDARD_ID_BYPASS_CODE"] unless StandardId::AppEnvironment.production?
|
|
878
888
|
```
|
|
879
889
|
|
|
880
|
-
`production_env_detector`
|
|
890
|
+
`production_env_detector` (a callable taking no arguments, returning a boolean)
|
|
891
|
+
still overrides that, for an app with a different discriminator.
|
|
881
892
|
|
|
882
893
|
**Back-compat.** The existing passwordless authentication flow continues to work unchanged. `Otp.issue`/`Otp.verify` are a new addition — you can migrate direct `CodeChallenge.create!` calls at your own pace.
|
|
883
894
|
|
|
@@ -1943,6 +1954,38 @@ Notes:
|
|
|
1943
1954
|
|
|
1944
1955
|
## Testing
|
|
1945
1956
|
|
|
1957
|
+
### Signing in from your app's request specs
|
|
1958
|
+
|
|
1959
|
+
```ruby
|
|
1960
|
+
# spec/rails_helper.rb
|
|
1961
|
+
require "standard_id/testing"
|
|
1962
|
+
|
|
1963
|
+
RSpec.configure do |config|
|
|
1964
|
+
config.include StandardId::Testing::RequestHelpers, type: :request
|
|
1965
|
+
end
|
|
1966
|
+
```
|
|
1967
|
+
|
|
1968
|
+
```ruby
|
|
1969
|
+
sign_in_as(account) # a real BrowserSession, via the session_token cookie
|
|
1970
|
+
sign_in_as(account, scope: :platform) # also grants standard_id_scopes (current_scope_names)
|
|
1971
|
+
get "/dashboard"
|
|
1972
|
+
|
|
1973
|
+
get "/api/orders", headers: bearer_headers_for(account, scope: "orders.read")
|
|
1974
|
+
```
|
|
1975
|
+
|
|
1976
|
+
`sign_in_as` creates a real `BrowserSession` and writes the same encrypted
|
|
1977
|
+
`session_token` cookie a real sign-in writes, so `current_account`,
|
|
1978
|
+
`require_browser_session!`, expiry and revocation behave exactly as in
|
|
1979
|
+
production. It adds nothing to your app: the cookies are built with your app's
|
|
1980
|
+
own encrypted cookie jar, so there is no test-only route. `scope:` writes the
|
|
1981
|
+
Rails session cookie and so needs the cookie session store (the Rails default);
|
|
1982
|
+
with another store it raises `ArgumentError`, and you sign in through your own
|
|
1983
|
+
scoped login request instead. It replaces controller stubbing
|
|
1984
|
+
(`stub_web_authentication`, `allow_any_instance_of(...).to receive(:current_user)`)
|
|
1985
|
+
and per-app `/test/set-session` routes.
|
|
1986
|
+
|
|
1987
|
+
### This gem's own suite
|
|
1988
|
+
|
|
1946
1989
|
StandardId includes comprehensive test coverage:
|
|
1947
1990
|
|
|
1948
1991
|
```bash
|
|
@@ -28,6 +28,8 @@ module StandardId
|
|
|
28
28
|
|
|
29
29
|
class_option :skip_initializer, type: :boolean, default: false,
|
|
30
30
|
desc: "Do not write config/initializers/standard_id.rb"
|
|
31
|
+
class_option :with_reference, type: :boolean, default: false,
|
|
32
|
+
desc: "Write the annotated initializer (every common setting with its default) instead of the minimal one"
|
|
31
33
|
class_option :skip_routes, type: :boolean, default: false,
|
|
32
34
|
desc: "Do not append engine mount lines to config/routes.rb"
|
|
33
35
|
class_option :skip_migrations, type: :boolean, default: false,
|
|
@@ -51,7 +53,8 @@ module StandardId
|
|
|
51
53
|
def create_initializer_file
|
|
52
54
|
return say_status("skip", "config/initializers/standard_id.rb (--skip-initializer)", :yellow) if options[:skip_initializer]
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
source = options[:with_reference] ? "standard_id_reference.rb" : "standard_id.rb"
|
|
57
|
+
template source, "config/initializers/standard_id.rb"
|
|
55
58
|
end
|
|
56
59
|
|
|
57
60
|
def mount_engines
|