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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +141 -2
- data/README.md +70 -14
- data/guides/integrating.md +14 -10
- data/guides/naming.md +13 -5
- data/guides/request-evidence.md +57 -13
- data/lib/clickwrap/configuration.rb +169 -40
- data/lib/clickwrap/doctor.rb +7 -2
- data/lib/clickwrap/dsl/retention_builder.rb +15 -0
- data/lib/clickwrap/ip_geolocation/trackdown_resolver.rb +16 -0
- data/lib/clickwrap/privacy.rb +28 -7
- data/lib/clickwrap/request_evidence_extractor.rb +17 -14
- data/lib/clickwrap/request_evidence_policy.rb +40 -36
- data/lib/clickwrap/services/validate_policy_references.rb +7 -15
- data/lib/clickwrap/version.rb +1 -1
- data/lib/clickwrap/vocabulary.rb +27 -0
- data/lib/generators/clickwrap/install_generator.rb +7 -3
- data/lib/generators/clickwrap/templates/initializer.rb.erb +40 -22
- metadata +2 -2
|
@@ -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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
data/lib/clickwrap/version.rb
CHANGED
data/lib/clickwrap/vocabulary.rb
CHANGED
|
@@ -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
|
|
32
|
-
#
|
|
33
|
-
#
|
|
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
|
|
32
|
-
#
|
|
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
|
|
255
|
-
# purpose and deletion period before writing this file; review both
|
|
256
|
-
#
|
|
257
|
-
#
|
|
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
|
-
#
|
|
276
|
-
#
|
|
277
|
-
#
|
|
278
|
-
#
|
|
279
|
-
#
|
|
280
|
-
#
|
|
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.
|
|
305
|
-
#
|
|
306
|
-
#
|
|
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
|
|
372
|
-
# recording blanks that later
|
|
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
|
-
#
|
|
382
|
-
#
|
|
383
|
-
#
|
|
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.
|
|
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-
|
|
10
|
+
date: 2026-08-20 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: actionpack
|