active_sanction 1.0.0 → 1.0.1

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: 63d579349c5ed0f731edbb3811cea143c2a1bdf7f591b319fb290ab6fb28c8c6
4
- data.tar.gz: e6ad0e3c72fdca696dc2d9e2e1d528a4a43e638054362f1ebf0931def9b309c8
3
+ metadata.gz: b6c9a31bd72dfdc43d5614499a19aab837b55996b9644ae145b89da18b93bea6
4
+ data.tar.gz: 40cbea7b7fcf458307171ca953fb61864dce06da7733ece2ac17e4d27a43215d
5
5
  SHA512:
6
- metadata.gz: '086eb3b75aa22d1cf3b976b269f28f49a0b5a734a22bba52f0a25119125042c40d41a35fc25b694069814d7f3d4e24426e51ef5da15f5d91f24c33519eff97f4'
7
- data.tar.gz: d5cf18bc582c46e84b1255328e5a8411bb6e35c5444c8660c2687b7be5621411333f0d3a782fd352ad0963ab96e72ed93f1abd3fb7349bccc073f4f02e2e4452
6
+ metadata.gz: 892209a20496c2eea1185776a83725cb89ae6c7b40ba2385becf7870b78d8e1a6cf88734e29afec40153418dfa73ac275a3270b0bb16a80e56c3de6605e58652
7
+ data.tar.gz: e3330620e4c4f6c31c6a7e0c58b53bda9972628e9d6965798d56f666f7301b83ccc2edb42931d15b18b161c9480df96b5147edf0e94b77461e90e0958944ed46
data/CHANGELOG.md CHANGED
@@ -13,6 +13,71 @@ algorithms or the scorer could move a score. **A change that moves `MATCHER_VERS
13
13
  called out here as such**, because it is the one kind of change that alters what a past
14
14
  screening decision would come out as today.
15
15
 
16
+ ## [Unreleased]
17
+
18
+ Nothing yet.
19
+
20
+ ## [1.0.1] - 2026-09-14
21
+
22
+ A packaging and release-tooling release. **Nothing about screening changes**: no behaviour
23
+ in `lib/` moved, `MATCHER_VERSION` is unchanged at `1`, and a name scores today exactly what
24
+ it scored under 1.0.0.
25
+
26
+ ### Added
27
+
28
+ - **Releases publish themselves from a tag**, through
29
+ [`.github/workflows/release.yml`](.github/workflows/release.yml). Pushing `v1.2.3` re-runs
30
+ the three gates against the tagged tree, checks that the tag and `VERSION` agree, that the
31
+ tag is an ancestor of `main` and that the changelog has a section for it, then builds the
32
+ gem, publishes it and writes the GitHub release from that section. A tag failing any of
33
+ those publishes nothing.
34
+
35
+ **No API key exists to leak.** It authenticates by
36
+ [trusted publishing](https://guides.rubygems.org/trusted-publishing): a short-lived OIDC
37
+ token, verified by rubygems.org as naming this repository and this workflow file, exchanged
38
+ for a credential that expires with the job. The alternative is a long-lived key in a public
39
+ repository's settings, one leak away from someone else publishing under this gem's name --
40
+ and unlike a bad deploy, a bad gem is already installed by the time anyone could be warned.
41
+ Same reasoning that keeps a service-account key out of the documentation deploy.
42
+
43
+ The gem pushed is the gem that was verified, carried between the two jobs as an artifact
44
+ rather than rebuilt -- a second build is a second thing, however identical it looks.
45
+
46
+ **The publish is confirmed against rubygems.org** (#136), because `gem push` exiting 0 says
47
+ the upload was accepted rather than that a `bundle install` will find the version. The job
48
+ that writes the GitHub release waits on that confirmation, so a version rubygems.org did not
49
+ end up serving is never announced.
50
+
51
+ - **A gem badge on the README** (#136), read live from rubygems.org rather than generated into
52
+ a file. What it states is what is installable, which is a different question from what was
53
+ last tagged -- and a version written into the repository would be stale the moment the next
54
+ one published. Same argument as #104, applied to the one fact about this gem that lives
55
+ somewhere else entirely.
56
+
57
+ - **A release can be cut from the Actions tab**, without tagging by hand (#139). The
58
+ workflow's "Run workflow" button takes a tag and a checkbox: ticked, it runs every gate
59
+ against `main` and writes the tag only once they have all passed. That is the safer order
60
+ than `git tag && git push`, which makes a tag public before anything has checked the tree
61
+ under it — and this workflow will not move a tag somebody may already have fetched, so the
62
+ repair for that is a new version number. A tag it writes is annotated but unsigned; push
63
+ the tag yourself when you want your own signature on it. See
64
+ [`CONTRIBUTING.md`](CONTRIBUTING.md#releasing).
65
+
66
+ ### Fixed
67
+
68
+ - **`rake canary:refresh` regenerates the catalogue page's data as well as the baselines.**
69
+ `site/src/data/sources.json` is derived from `.github/baselines` (#104), so accepting new
70
+ numbers without rebuilding it left the two disagreeing and
71
+ [`spec/site_sources_data_spec.rb`](spec/site_sources_data_spec.rb) red. The rolling
72
+ baseline pull request the canary opens had failed on this every run since it started
73
+ opening one, on all six Rubies. Chained onto the task rather than added as a step to each
74
+ caller: a derived file that callers have to remember to rebuild is stale by the third
75
+ caller.
76
+
77
+ - **The canary signs its baseline commit off.** Nothing exempts a bot from
78
+ [`.github/workflows/dco.yml`](.github/workflows/dco.yml), which skips merge commits and
79
+ nothing else, so the rolling pull request failed the DCO check as well.
80
+
16
81
  ## [1.0.0] - 2026-09-13
17
82
 
18
83
  The first release. Everything below is in it.
@@ -535,4 +600,6 @@ summarized here because they are what a reader of a first release most needs:
535
600
  - Recall at the default threshold is 0.939 overall on the labeled set, and every record this
536
601
  version misses is named in the committed accuracy report.
537
602
 
603
+ [Unreleased]: https://github.com/Babystep-Technologies/active_sanction/compare/v1.0.1...main
604
+ [1.0.1]: https://github.com/Babystep-Technologies/active_sanction/compare/v1.0.0...v1.0.1
538
605
  [1.0.0]: https://github.com/Babystep-Technologies/active_sanction/releases/tag/v1.0.0
data/CONTRIBUTING.md CHANGED
@@ -232,11 +232,75 @@ comment restating the name would be noise.
232
232
 
233
233
  ## Releasing
234
234
 
235
- `bundle exec rake install` installs the gem locally. A release is: bump
236
- `VERSION` in [`lib/active_sanction/version.rb`](lib/active_sanction/version.rb),
237
- move the `Unreleased` section of [`CHANGELOG.md`](CHANGELOG.md) under the new
238
- version with its date, then `bundle exec rake release`, which tags, pushes
239
- and publishes to [rubygems.org](https://rubygems.org).
235
+ `bundle exec rake install` installs the gem locally.
236
+
237
+ A release is a tag. Bump `VERSION` in
238
+ [`lib/active_sanction/version.rb`](lib/active_sanction/version.rb), move the
239
+ `Unreleased` section of [`CHANGELOG.md`](CHANGELOG.md) under the new version
240
+ with its date, and merge that.
241
+
242
+ Then the tag, which you can let the workflow write or write yourself.
243
+
244
+ **From the Actions tab**, which is the shorter path and the safer order. Open
245
+ [`Release`](https://github.com/Babystep-Technologies/active_sanction/actions/workflows/release.yml),
246
+ press **Run workflow**, enter `v1.2.3`, and tick **Create the tag on main**.
247
+ Every gate runs against `main` first, and the tag is written only once they
248
+ have all passed — so a release that turns out not to be publishable leaves no
249
+ tag behind.
250
+
251
+ **Or from a terminal**, which is the path to take when you want your own
252
+ signature on the tag:
253
+
254
+ $ git tag -s v1.2.3 -m "Release 1.2.3"
255
+ $ git push origin v1.2.3
256
+
257
+ The cost of that order is that the tag is public before anything has checked
258
+ the tree under it. If a gate then fails, the tag stays where it is: this
259
+ workflow will not move a tag somebody may already have fetched, so the repair
260
+ is a new version rather than a retagged one.
261
+
262
+ Either way, [`.github/workflows/release.yml`](.github/workflows/release.yml)
263
+ does the rest. It re-runs the three gates against the tree being released,
264
+ checks that the tag and `VERSION` agree, that the commit is on `main`, and
265
+ that the changelog has a section for it — then builds the gem, publishes it to
266
+ [rubygems.org](https://rubygems.org), confirms rubygems.org is serving that
267
+ version, and writes the GitHub release from that changelog section. A release
268
+ that fails any of those checks publishes nothing, and a push rubygems.org did
269
+ not end up serving is never announced (#136).
270
+
271
+ **Leave the box unticked to re-run a publish.** A dispatch with `Create the
272
+ tag` unticked publishes a tag that already exists — one pushed before this
273
+ workflow did, or one whose publish failed after the tag was public — and
274
+ nothing in this workflow ever moves or deletes a tag. Ticking the box against
275
+ a tag that already exists is not an error either; it publishes that tag and
276
+ says it created nothing.
277
+
278
+ **A tag the workflow writes is annotated but not signed.** It has no key of
279
+ yours, and signing with a machine key would say less than saying nothing. The
280
+ tag names the commit every gate ran against, and the provenance that matters
281
+ for what users install is on the other side: the gem is published by [trusted
282
+ publishing](https://guides.rubygems.org/trusted-publishing) from this
283
+ repository and this workflow file. Sign the tag yourself, with the terminal
284
+ path above, when you want the tag to carry it too.
285
+
286
+ The [gem badge](https://rubygems.org/gems/active_sanction) at the top of the
287
+ README reads from rubygems.org rather than from anything in this repository,
288
+ so it states what is installable rather than what was last tagged.
289
+
290
+ **Nobody needs a RubyGems API key, including the person tagging.** The
291
+ workflow authenticates by [trusted
292
+ publishing](https://guides.rubygems.org/trusted-publishing): it mints a
293
+ short-lived OIDC token, rubygems.org verifies the token names this repository
294
+ and this workflow file, and hands back a credential that expires with the job.
295
+ There is no publishing secret in this repository's settings, for the same
296
+ reason there is no service-account key for the documentation deploy. It is
297
+ configured once, on rubygems.org, under the gem's **Trusted Publishers**:
298
+ owner `Babystep-Technologies`, repository `active_sanction`, workflow
299
+ `release.yml`, environment `rubygems`.
300
+
301
+ `bundle exec rake release` — the manual path that tags, pushes and publishes
302
+ in one step — still exists and still works for anyone with push rights to the
303
+ gem. It is not how this gem is released, and using it skips every check above.
240
304
 
241
305
  `MATCHER_VERSION` in the same file is bumped on a different occasion and for
242
306
  a different reason — whenever a change to the normalizer, the index, the
data/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  # ActiveSanction
6
6
 
7
+ [![Gem](https://img.shields.io/gem/v/active_sanction?label=gem&color=CC342D)](https://rubygems.org/gems/active_sanction)
7
8
  [![CI](https://github.com/Babystep-Technologies/active_sanction/actions/workflows/ci.yml/badge.svg)](https://github.com/Babystep-Technologies/active_sanction/actions/workflows/ci.yml)
8
9
 
9
10
  **[Full documentation, guides and the source catalogue →](https://babystep.tech/active_sanction/)**
@@ -110,6 +110,24 @@ module ActiveSanction
110
110
  # per source: a list that failed to refresh keeps its previous snapshot,
111
111
  # which is the right call and only safe if the age of what is being
112
112
  # screened against is visible.
113
+ #
114
+ # **Accurate to a second, and never fewer than the seconds that have
115
+ # passed.** `fetched_at` is stored to the second -- Snapshot#time!
116
+ # truncates it, so that a stored snapshot reloads equal to the one that
117
+ # was written -- so the instant of the fetch is known only to lie
118
+ # somewhere inside the second this names. What comes back is therefore
119
+ # the largest age consistent with what was recorded, which is the
120
+ # direction a staleness measure has to err in: an answer that is at most
121
+ # a second pessimistic is a report that nobody acts on, and one that is
122
+ # optimistic is a list being screened against that is older than it
123
+ # claims.
124
+ #
125
+ # The practical consequence, and the reason it is written down: a list
126
+ # fetched microseconds ago reports 0 or 1, according to whether the run
127
+ # crossed a second boundary on its way here. Both mean "just fetched" --
128
+ # see Sync::Result#age_in_words, which is what a summary table shows --
129
+ # and nothing should assert on the exact number of a fresh sync, because
130
+ # that is a fact about the clock rather than about this library.
113
131
  sig { params(now: Time).returns(Integer) }
114
132
  def age(now = Time.now) = now.to_i - fetched_at.to_i
115
133
 
@@ -6,7 +6,7 @@ module ActiveSanction
6
6
  # new source adapter, a storage fix or a documentation release -- none of
7
7
  # which change what a name scores. MATCHER_VERSION, below, is the one that
8
8
  # answers that question.
9
- VERSION = "1.0.0"
9
+ VERSION = "1.0.1"
10
10
 
11
11
  # Which matching pipeline scored a decision, stamped onto every MatchResult
12
12
  # and bumped whenever a change to the normalizer, the index, the similarity
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_sanction
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marshall Shen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-09-13 00:00:00.000000000 Z
11
+ date: 2026-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: csv