clickwrap 0.2.0 → 0.3.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.
@@ -15,7 +15,6 @@ module Clickwrap
15
15
  Clickwrap.policies.each do |policy|
16
16
  validate_documents!(policy)
17
17
  retention_class = validate_retention_class!(policy)
18
- validate_request_evidence_retention!(policy, retention_class)
19
18
  validate_host_calculations!(policy, retention_class)
20
19
  validate_authority_adapter!(policy)
21
20
  validate_ip_geolocation_resolver!(policy)
@@ -105,20 +104,13 @@ module Clickwrap
105
104
  )
106
105
  end
107
106
 
108
- def validate_request_evidence_retention!(policy, retention_class)
109
- RequestEvidencePolicy::FIELD_CATEGORIES.each do |category|
110
- setting = policy.request_evidence.setting_for(category)
111
- next unless setting.record?
112
- next if setting.delete_after || setting.retain_until || retention_class.rule_for(category)
113
-
114
- raise DefinitionError,
115
- "Policy #{policy.key} records #{category}, but neither that policy nor retention " \
116
- "class #{retention_class.key} says when to dispose of it. Add " \
117
- "`delete_after:`/`retain_until:` to the policy or the matching plain-English " \
118
- "request-evidence rule to the retention class."
119
- end
120
- end
121
-
107
+ # There is deliberately no disposal check here any more. A recorded
108
+ # category with no clock anywhere — not on the policy, not in its
109
+ # retention class, not in the initializer — means it keeps pace with the
110
+ # evidence it corroborates, which is what the core event does by default
111
+ # too. What still fails below is a rule that names a calculation nobody
112
+ # registered: a deadline waiting on a typo never arrives, and that is a
113
+ # different thing from a deliberate absence of one.
122
114
  def validate_host_calculations!(policy, retention_class)
123
115
  referenced = retention_class.rules.values.filter_map do |rule|
124
116
  rule.host_event_name&.to_sym
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Clickwrap
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
 
6
6
  # The canonical schema version for receipts, event digests, and presentation
7
7
  # manifests. This is deliberately independent of VERSION: gem releases may
@@ -160,6 +160,33 @@ module Clickwrap
160
160
  accuracy_radius_in_kilometers
161
161
  ].freeze
162
162
 
163
+ # The three coarse fields `config.record_request_evidence_by_default = true`
164
+ # turns on. Coarse means administrative area, not a point: a country, a
165
+ # region, and a city are what a provider can estimate from an address with
166
+ # any confidence at all. Everything finer — a postal code, coordinates, a
167
+ # timezone, a metro code — stays its own separately named decision, because
168
+ # a switch that reads "record request evidence" should not hand somebody
169
+ # coordinates they never asked for.
170
+ COARSE_IP_GEOLOCATION_DATA_FIELDS = %w[country region city].freeze
171
+
172
+ # The purpose Clickwrap records when a host enables request evidence
173
+ # without writing a purpose of their own. It is the gem's own sentence, not
174
+ # a reviewed host decision, and the privacy inventory says which of the two
175
+ # it is looking at. It exists because the alternative — refusing to boot
176
+ # until somebody writes a sentence — was pushing integrators to record
177
+ # nothing at all, and no corroboration is worse evidence than corroboration
178
+ # collected under the gem's stated purpose.
179
+ DEFAULT_REQUEST_EVIDENCE_PURPOSE =
180
+ "Corroborate who performed each recorded act, from where, on what client — to defend " \
181
+ "the recorded agreement itself."
182
+
183
+ # The reason recorded when a host keeps request evidence indefinitely
184
+ # without writing their own. Same posture as the purpose above: the
185
+ # declaration is still recorded and still readable years later; only the
186
+ # obligation to phrase it yourself is gone.
187
+ DEFAULT_REASON_FOR_KEEPING_REQUEST_EVIDENCE_INDEFINITELY =
188
+ "Corroboration lives as long as the evidence it corroborates"
189
+
163
190
  # Provenance that travels with any stored IP-geolocation result. A policy
164
191
  # cannot keep provider-derived coordinates while stripping the uncertainty
165
192
  # needed to interpret them.
@@ -28,9 +28,13 @@ module Clickwrap
28
28
  # spelling of the off-by-default posture. It disappears after generation;
29
29
  # it is deliberately not a runtime concept. There is no
30
30
  # `record_network_context`, `record_everything`, `full_evidence`, or
31
- # regulation-named mode switch anywhere in this gem, because a flag that
32
- # enables a whole category of personal data is the thing this gem exists not
33
- # to do, and no flag can make a legal determination on a host's behalf.
31
+ # regulation-named mode switch anywhere in this gem, because a flag whose
32
+ # name hides what it collects is the thing this gem exists not to ship, and
33
+ # no flag can make a legal determination on a host's behalf. The runtime's
34
+ # one grouped switch, `config.record_request_evidence_by_default`, is not
35
+ # one of those: it names its three fields and can never grow a fourth. The
36
+ # installer still asks about them one at a time, because a purpose the host
37
+ # wrote beats the honest default the gem would otherwise record.
34
38
  class InstallGenerator < Rails::Generators::Base
35
39
  include ActiveRecord::Generators::Migration
36
40
 
@@ -28,8 +28,11 @@
28
28
  #
29
29
  # There is deliberately no `maximum_evidence`, `full_evidence`, `legal_proof`,
30
30
  # or regulation-named mode setting. No runtime flag can make a legal
31
- # determination for you, and an option that turns on a category of personal data
32
- # as a side effect of something else is exactly what this gem exists not to do.
31
+ # determination for you, and an option whose name does not say what it collects
32
+ # is exactly what this gem exists not to ship. The one grouped switch that does
33
+ # exist, `config.record_request_evidence_by_default`, names its own contents:
34
+ # an IP address, a browser user agent, and a coarse country/region/city
35
+ # estimate — nothing finer, ever.
33
36
  <%- if recipe -%>
34
37
  #
35
38
  # This file was scaffolded with `--request-evidence-recipe=<%= recipe %>`. The
@@ -251,10 +254,12 @@ Clickwrap.configure do |config|
251
254
  # proof that anyone was physically anywhere.
252
255
  <%- if records_any_request_evidence? -%>
253
256
  #
254
- # You enabled some of these during install. The generator required an explicit
255
- # purpose and deletion period before writing this file; review both below. The
256
- # annex table itself came with `--with-request-evidence`, which this install
257
- # added for you.
257
+ # You enabled some of these during install, and the installer asked for an
258
+ # explicit purpose and deletion period before writing this file; review both
259
+ # below. The gem itself would have accepted the fields without them and
260
+ # recorded its own stated purpose instead — the installer asks because a
261
+ # sentence your team wrote is worth more than one the gem supplied. The annex
262
+ # table came with `--with-request-evidence`, which this install added for you.
258
263
  <%- else -%>
259
264
  #
260
265
  # Everything here is off, which is the safe default — and the annex table was
@@ -272,12 +277,15 @@ Clickwrap.configure do |config|
272
277
 
273
278
  # --- Request evidence: why, how long, and how it is protected ---------------
274
279
  #
275
- # An enabled field with a blank purpose or no deletion rule is a configuration
276
- # error at boot, not a warning. "We turned it on and never decided why" is the
277
- # failure mode these settings exist to prevent. There is no keep-forever
278
- # default anywhere in this gem, and deleting a value removes the encrypted
279
- # annex entry and appends a disposition event the historical agreement,
280
- # declaration, or authorization stays intact and verifiable without it.
280
+ # Both of these are optional, and the installer wrote yours because you gave
281
+ # them. A field enabled with no purpose records the one Clickwrap states, and
282
+ # the privacy inventory marks it as the gem's sentence rather than yours; a
283
+ # field with no deletion period keeps pace with the evidence it corroborates.
284
+ # What is refused is a purpose that is still scaffolding text, and a deletion
285
+ # period set alongside `keep_recorded_..._indefinitely!` for the same field.
286
+ # Deleting a value removes the encrypted annex entry and appends a disposition
287
+ # event — the historical agreement, declaration, or authorization stays intact
288
+ # and verifiable without it.
281
289
 
282
290
  <%- if record_ip_addresses? -%>
283
291
  config.reason_for_recording_ip_addresses_by_default =
@@ -301,10 +309,10 @@ Clickwrap.configure do |config|
301
309
  config.review_default_request_evidence_configuration_on = <%= review_date_literal %>
302
310
  <%- else -%>
303
311
  # Nothing above is enabled, so there is nothing to give a purpose or a
304
- # deletion period to. Enabling a field is never one line — the gem refuses an
305
- # enabled field with no recorded purpose and no deletion rule — and it wants a
306
- # review date so the decision gets looked at again by a person instead of
307
- # outliving its reason:
312
+ # deletion period to. Turning the ordinary three on later is one line —
313
+ # `config.record_request_evidence_by_default = true` — and these are the
314
+ # settings that upgrade it into a record your own team reviewed, plus a date
315
+ # so the decision gets looked at again instead of outliving its reason:
308
316
  #
309
317
  # config.reason_for_recording_ip_addresses_by_default = "Investigate disputed submissions"
310
318
  # config.delete_recorded_ip_addresses_after = 90.days
@@ -359,7 +367,9 @@ Clickwrap.configure do |config|
359
367
  Clickwrap.trusted_proxy_configuration_digest_for_rails_application
360
368
  <%- else -%>
361
369
  # A digest of the effective trusted-proxy rules, stored beside any recorded
362
- # address. Nothing here records one, so there is nothing to stamp:
370
+ # address. Nothing here records one, so there is nothing to stamp. Set it if
371
+ # you enable IP recording later: it is not required, but without it every
372
+ # recorded address carries a blank where its collection context should be.
363
373
  #
364
374
  # config.trusted_proxy_configuration_digest =
365
375
  # Clickwrap.trusted_proxy_configuration_digest_for_rails_application
@@ -368,8 +378,9 @@ Clickwrap.configure do |config|
368
378
  <%- if any_ip_geolocation_field? -%>
369
379
  # DECISION — you enabled IP-geolocation fields and explicitly selected this
370
380
  # resolver. Make its gem and data source available in every environment:
371
- # Clickwrap refuses to boot with fields it has nothing to resolve, rather than
372
- # recording blanks that later read as "no result".
381
+ # Clickwrap refuses to boot with fields nothing can resolve no resolver here
382
+ # and no trackdown in the bundle — rather than recording blanks that later
383
+ # read as "no result".
373
384
  #
374
385
  # Only the fields authorized above are stored, never the whole result object,
375
386
  # and every stored value keeps the provider, source, estimated state,
@@ -378,11 +389,18 @@ Clickwrap.configure do |config|
378
389
  # needed to read them.
379
390
  config.ip_geolocation_resolver = <%= ip_geolocation_resolver_class_name %>.new
380
391
  <%- else -%>
381
- # Required before any IP-geolocation field can be enabled, here or in a
382
- # policy. The official optional resolver requires trackdown >= 0.4 so the
383
- # provider that actually answered and per-request source trust are preserved:
392
+ # Something has to resolve an IP-geolocation field before it can be enabled,
393
+ # here or in a policy. Bundling trackdown is enough Clickwrap uses the
394
+ # official adapter for you when you have not named a resolver of your own,
395
+ # and the privacy inventory reports it as the gem's choice rather than yours.
396
+ # It requires trackdown >= 0.4 so the provider that actually answered and
397
+ # per-request source trust are preserved:
384
398
  #
385
399
  # bundle add trackdown --version ">= 0.4"
400
+ #
401
+ # Name it explicitly to pick a different provider, or when you are wiring
402
+ # Trackdown's per-request CDN trust:
403
+ #
386
404
  # config.ip_geolocation_resolver = Clickwrap::IpGeolocation::TrackdownResolver.new
387
405
  <%- end -%>
388
406
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clickwrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - rameerez
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-08-19 00:00:00.000000000 Z
10
+ date: 2026-08-20 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: actionpack