analytics_ops 0.1.0 → 0.2.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +232 -41
  5. data/SECURITY.md +8 -8
  6. data/docs/api-support-matrix.md +9 -8
  7. data/docs/architecture.md +22 -4
  8. data/docs/authentication.md +112 -51
  9. data/docs/commands.md +71 -17
  10. data/docs/configuration-schema-v1.json +53 -7
  11. data/docs/configuration.md +33 -9
  12. data/docs/google-client-compatibility.md +10 -6
  13. data/docs/live-smoke-test.md +159 -0
  14. data/docs/plan-format.md +4 -0
  15. data/docs/plan-schema-v1.json +113 -22
  16. data/docs/rails.md +12 -3
  17. data/docs/reports.md +44 -6
  18. data/docs/safety.md +18 -6
  19. data/docs/troubleshooting.md +42 -13
  20. data/lib/analytics_ops/applier.rb +2 -1
  21. data/lib/analytics_ops/cli/options.rb +157 -0
  22. data/lib/analytics_ops/cli/presenter.rb +221 -0
  23. data/lib/analytics_ops/cli.rb +172 -201
  24. data/lib/analytics_ops/clients/admin.rb +130 -129
  25. data/lib/analytics_ops/clients/admin_normalization.rb +95 -0
  26. data/lib/analytics_ops/clients/data.rb +120 -63
  27. data/lib/analytics_ops/clients/error_translation.rb +45 -0
  28. data/lib/analytics_ops/configuration/document.rb +1 -1
  29. data/lib/analytics_ops/configuration/loader.rb +38 -5
  30. data/lib/analytics_ops/configuration/schema.rb +51 -8
  31. data/lib/analytics_ops/configuration/validator.rb +43 -8
  32. data/lib/analytics_ops/configuration/writer.rb +105 -0
  33. data/lib/analytics_ops/configuration.rb +1 -0
  34. data/lib/analytics_ops/connection.rb +93 -0
  35. data/lib/analytics_ops/desired_state.rb +2 -2
  36. data/lib/analytics_ops/plan.rb +94 -33
  37. data/lib/analytics_ops/planner.rb +10 -2
  38. data/lib/analytics_ops/rails/railtie.rb +13 -18
  39. data/lib/analytics_ops/redaction.rb +14 -9
  40. data/lib/analytics_ops/reports/catalog.rb +22 -5
  41. data/lib/analytics_ops/reports/definition.rb +74 -37
  42. data/lib/analytics_ops/reports/overview.rb +55 -0
  43. data/lib/analytics_ops/reports/overview_result.rb +54 -0
  44. data/lib/analytics_ops/reports/result.rb +38 -9
  45. data/lib/analytics_ops/reports.rb +2 -0
  46. data/lib/analytics_ops/resources.rb +2 -1
  47. data/lib/analytics_ops/service_account.rb +171 -0
  48. data/lib/analytics_ops/setup.rb +171 -0
  49. data/lib/analytics_ops/snapshot.rb +20 -5
  50. data/lib/analytics_ops/version.rb +1 -1
  51. data/lib/analytics_ops/workspace.rb +41 -12
  52. data/lib/analytics_ops.rb +4 -0
  53. data/lib/generators/analytics_ops/install_generator.rb +2 -0
  54. data/lib/generators/analytics_ops/templates/analytics_ops.yml +2 -15
  55. data/sig/analytics_ops.rbs +117 -10
  56. metadata +26 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bf17db3adc805f77cf7d22e2ea2840a3eaf44a007be8036a48bf58a4d2d3a36
4
- data.tar.gz: 1642e17fb59a976a471636a92f8da2f1290c3e13eb7bee515722efd8315a2e4a
3
+ metadata.gz: f71655d305efa516ee61d1d1059078f6e0bd562949a542e764dceff69eb58017
4
+ data.tar.gz: d73a4e6cb8aa1de4ec019104bcc28ab259be236dd41612f73be4124a0f4bae56
5
5
  SHA512:
6
- metadata.gz: c934c5e8856505c2ec5d8e4311ac9f9e3d23ba47078fc478170dcda4d08e5d5be990402fa2795d56138ba30d2c8e92dbe368fdb1fb3da254bead9ba429338f09
7
- data.tar.gz: b96a8112f501416f763d3528419435e2364526f66cd43266ec3880825f61c964550eca739ece89607d7d89a583051b44d35d1f3f62a018260dab625d13a871ef
6
+ metadata.gz: ff58c5f35e8573755d4dab309163602124fda905aa2e452568e04ceef4d12d8b370e2d573b7783ab150b6083c2657dbf9cf03e6c4124ca8931cfe4ef01966679
7
+ data.tar.gz: 5495494e5cae8ba1a786644752038a5749cf4aa2cdb05cbfc12da0923c8558596be1391b3f1806cf7739ea6ad13ea57a01150ff0e69e2f4e57a86232ab14df86
data/CHANGELOG.md CHANGED
@@ -3,6 +3,82 @@
3
3
  Analytics Ops follows Semantic Versioning for its public Ruby, CLI,
4
4
  configuration, and plan contracts.
5
5
 
6
+ ## [0.2.0] - 2026-07-22
7
+
8
+ ### Added
9
+
10
+ - Configuration-free `properties` and `discover` commands, removing the
11
+ property-ID onboarding deadlock.
12
+ - Service-account-only `setup` with strict JSON-key validation, numbered
13
+ property selection, effective API access checks, and non-interactive
14
+ automation support.
15
+ - Atomic mode-`0600` user-level connection storage that remembers only the
16
+ service-account key path and never copies the key.
17
+ - Non-destructive atomic creation of the smallest valid `production`
18
+ configuration. Matching configuration is reused; conflicting profiles are
19
+ never overwritten.
20
+ - A five-section, row-bounded `overview` powered by one official
21
+ `batchRunReports` request, with immutable normalized results and property
22
+ quota metadata.
23
+ - Friendly `traffic` and `landing-pages` report aliases plus `--json` and
24
+ `--csv` format shortcuts.
25
+ - Optional Rails `analytics:overview` Rake task.
26
+ - A public real-app read-only smoke-test and release-gate guide using the
27
+ single service-account authentication path.
28
+
29
+ ### Changed
30
+
31
+ - Account/property-only discovery no longer fetches every property's streams;
32
+ detailed `discover` retains the original stream output.
33
+ - The setup, connection, overview, CLI, Google-client, RBS, and operator
34
+ documentation now describe the simpler three-command start.
35
+ - Currency custom metrics now carry Google's required cost/revenue restricted-
36
+ data classification through configuration, snapshots, plans, and requests.
37
+ - Rails installation now generates a minimal property-only configuration, so
38
+ sample stream or retention values cannot become accidental changes.
39
+ - The Rails generator preserves configuration already created by setup and
40
+ adds the binstub without an overwrite prompt.
41
+ - Every CLI and Ruby orchestration path now loads an explicit service account;
42
+ ambient credentials, API keys, browser login, and external CLI
43
+ authentication are not fallback paths.
44
+ - `googleauth` is now a direct reviewed dependency because Analytics Ops calls
45
+ its service-account loader explicitly.
46
+ - Read-only operations request only `analytics.readonly`; guarded apply
47
+ creates a separate client with `analytics.edit`.
48
+
49
+ ### Fixed
50
+
51
+ - Keep empty rows for dimensionless standard reports so overview totals retain
52
+ their metric headers on a new or empty GA4 property.
53
+ - Use only Google's compatible `eventCount` metric in the built-in
54
+ `realtime_events` recipe.
55
+ - Reject duplicate or excessively nested YAML, impossible user-retention
56
+ periods, Google-invalid custom-definition display names, oversized stream
57
+ URIs, reversed report dates, malformed numeric filters, and non-finite
58
+ client options before calling Google.
59
+ - Preserve Google's automatic `dateRange` column, distinguish absent report
60
+ metadata, validate quota/row/header shapes, and reject invalid UTF-8 output.
61
+ - Translate pagination and raw socket failures into typed errors and reject
62
+ malformed or cross-property Admin responses.
63
+ - Require the literal boolean `true` for Ruby apply confirmation and reject
64
+ non-web, cross-property, or otherwise forged saved-plan payloads.
65
+ - Handle Ctrl-C as clean human or JSON output with exit status 130 instead of
66
+ dumping a Ruby backtrace.
67
+
68
+ ### Security
69
+
70
+ - Setup validates a bounded service-account key and stores only its canonical
71
+ path outside the project; keys never enter configuration, plans, logs, or
72
+ output.
73
+ - Setup verifies access before writing configuration or remembering the key
74
+ path, and non-interactive mode never prompts.
75
+ - Credential-shaped values are rejected from configuration and plans; JSON
76
+ secret assignments, invalid bytes, and terminal controls are sanitized.
77
+ - Human output is terminal-safe, and CSV formula protection covers headers and
78
+ values hidden behind whitespace or controls.
79
+ - Existing guarded apply, stale-plan, no-delete, redaction, and no-network-on-
80
+ load guarantees remain unchanged.
81
+
6
82
  ## [0.1.0] - 2026-07-22
7
83
 
8
84
  ### Added
data/CONTRIBUTING.md CHANGED
@@ -26,7 +26,8 @@ mounted read-only except for source edits.
26
26
  ## Design rules
27
27
 
28
28
  - Keep the core plain Ruby and independent of Rails and Active Support.
29
- - Use Google's official Ruby clients; do not add another HTTP or OAuth stack.
29
+ - Use Google's official Ruby clients and the service-account-only contract; do
30
+ not add another HTTP or authentication stack.
30
31
  - Keep generated Google objects behind adapters.
31
32
  - Do not introduce telemetry, a database, browser analytics, or boot-time
32
33
  network access.
data/README.md CHANGED
@@ -6,51 +6,226 @@ Analytics Ops gives you a review-first way to inspect GA4, detect drift, run
6
6
  useful reports, and apply a small set of safe configuration changes. The core
7
7
  is plain Ruby; Rails support is optional.
8
8
 
9
- ## Five-minute read-only start
9
+ ## Three-command start
10
10
 
11
- You need Ruby 3.2 or newer, a GA4 property you can read, and the
12
- [Google Cloud CLI](https://cloud.google.com/sdk/docs/install).
11
+ You need Ruby 3.2 or newer, access to a GA4 property, and a Google
12
+ service-account JSON key kept outside the repository.
13
13
 
14
- 1. Add Analytics Ops to your bundle:
14
+ ```bash
15
+ gem install analytics_ops
16
+ analytics-ops setup --service-account /absolute/path/to/service-account.json
17
+ analytics-ops overview
18
+ ```
19
+
20
+ `setup` lists the properties the service account can access, lets you choose
21
+ one, and creates the smallest valid `config/analytics_ops.yml` for the default
22
+ `production` profile. It securely remembers the key's path, so every later
23
+ command works without another authentication option. You do not need
24
+ `gcloud`, browser authorization, a property ID, or hand-written YAML.
25
+
26
+ `overview` makes one bounded batch request and shows totals, a daily trend,
27
+ traffic acquisition, landing pages, and devices for the previous 28 complete
28
+ days. Both commands are read-only in Google Analytics.
29
+
30
+ ## Google Analytics setup (first time only)
31
+
32
+ The setup is easier when you keep these four separate things in mind:
33
+
34
+ | Item | What it does |
35
+ | --- | --- |
36
+ | Human Google Account | The account you use to sign in to Google Analytics and Google Cloud |
37
+ | GA4 account and property | Holds your website's analytics configuration and collected data |
38
+ | Google Cloud project | Owns API access, quota, and the service account; it does not hold your GA4 report data |
39
+ | Service account | The non-human identity Analytics Ops uses to call Google's APIs |
40
+
41
+ ### A. Create GA4 only if you do not already have it
42
+
43
+ Already have a working GA4 property collecting website data? Skip to
44
+ [Create the Google Cloud project](#b-create-the-google-cloud-project).
45
+
46
+ 1. Sign in at [Google Analytics](https://analytics.google.com).
47
+ 2. Click **Start Measuring**, or open **Admin → Create → Account**.
48
+ 3. Create an Analytics account.
49
+ 4. Create a GA4 property and choose its reporting time zone and currency.
50
+ 5. Create a Web data stream using your website URL.
51
+ 6. Install the resulting Google tag or Measurement ID on your website.
52
+
53
+ Analytics Ops reads and manages an existing GA4 property. It does not install
54
+ the website tracking tag or send browser events.
55
+
56
+ ### B. Create the Google Cloud project
57
+
58
+ 1. Sign in at [Google Cloud](https://console.cloud.google.com).
59
+ 2. Open the project selector and choose **New Project**.
60
+ 3. Use a clear name such as **Analytics Ops**.
61
+ 4. Choose **No organization** if you use a personal account. That is fine.
62
+ 5. Create the project and make sure it is selected before continuing.
63
+
64
+ Google requires this separate project for API access, quota, and the service
65
+ account identity. Creating it does not create another GA4 account or move your
66
+ analytics data.
67
+
68
+ ### C. Enable the two required APIs
69
+
70
+ In the selected Cloud project, open **APIs & Services → Library** and enable
71
+ exactly:
72
+
73
+ - **Google Analytics Admin API**
74
+ - **Google Analytics Data API**
75
+
76
+ You do not need the Gemini API.
77
+
78
+ ### D. Create the service account
79
+
80
+ 1. Open **IAM & Admin → Service Accounts**.
81
+ 2. Click **Create service account**.
82
+ 3. Use a name such as **Analytics Ops Local**.
83
+ 4. Continue past the optional Cloud permissions step without assigning
84
+ **Owner**, **Editor**, or another broad Cloud IAM role.
85
+ 5. Finish creating the service account.
86
+ 6. Copy its email address. It resembles:
87
+ `analytics-ops@example-project.iam.gserviceaccount.com`.
88
+
89
+ Google Cloud IAM Editor and GA4 Editor are different roles. The service
90
+ account does not need the Cloud IAM Editor role.
91
+
92
+ ### E. Download and protect the JSON key
93
+
94
+ 1. Open the service account you just created.
95
+ 2. Open **Keys**.
96
+ 3. Choose **Add key → Create new key → JSON**.
97
+ 4. Download the key.
98
+ 5. Move it to a stable location outside every application repository.
99
+ 6. On macOS or Linux, protect it with mode `0600`:
100
+
101
+ ```bash
102
+ mkdir -p ~/.config/analytics_ops
103
+ chmod 700 ~/.config/analytics_ops
104
+ mv /path/to/downloaded-key.json \
105
+ ~/.config/analytics_ops/service-account.json
106
+ chmod 600 ~/.config/analytics_ops/service-account.json
107
+ ```
108
+
109
+ Protect this file like a password:
15
110
 
16
- ```ruby
17
- # Gemfile
18
- gem "analytics_ops", "~> 0.1", group: :development
19
- ```
111
+ - Never commit it.
112
+ - Never paste its contents into chat, logs, screenshots, issues, or
113
+ environment variables.
114
+ - Do not put it inside `config/analytics_ops.yml`.
115
+ - If it is exposed, revoke the key in Google Cloud and create a replacement.
20
116
 
21
- ```bash
22
- bundle install
23
- ```
117
+ ### F. Give the service account GA4 access
24
118
 
25
- 2. Enable the Google Analytics Admin API and Data API in your own Google Cloud
26
- project, then create local Application Default Credentials:
119
+ 1. Return to [Google Analytics](https://analytics.google.com).
120
+ 2. Select the correct GA4 account and property.
121
+ 3. Open **Admin**.
122
+ 4. Choose **Property access management** for one property, or **Account access
123
+ management** for every property in that GA4 account.
124
+ 5. Click **+ → Add users**.
125
+ 6. Paste the service-account email.
126
+ 7. Disable **Notify new users by email**. A service account has no human
127
+ inbox.
128
+ 8. Select **Viewer** for reports, discovery, snapshots, doctor, and audit.
129
+ Select **Editor** only if you plan to use reviewed `apply` operations
130
+ later.
131
+ 9. Do not grant **Administrator**. Analytics Ops does not manage GA4 users.
132
+ 10. Click **Add**.
27
133
 
28
- ```bash
29
- gcloud auth application-default login \
30
- --scopes="https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/analytics.readonly"
31
- ```
134
+ Your human Google Account must already have permission to manage users in
135
+ that GA4 account or property.
32
136
 
33
- 3. Create `config/analytics_ops.yml`:
137
+ ### G. Install and connect Analytics Ops
34
138
 
35
- ```yaml
36
- version: 1
139
+ For a standalone installation:
37
140
 
38
- profiles:
39
- production:
40
- property_id: "123456789"
41
- ```
141
+ ```bash
142
+ gem install analytics_ops
143
+ analytics-ops setup \
144
+ --service-account ~/.config/analytics_ops/service-account.json
145
+ ```
146
+
147
+ For an application that uses Bundler, add:
148
+
149
+ ```ruby
150
+ # Gemfile
151
+ gem "analytics_ops", "~> 0.2", group: :development
152
+ ```
153
+
154
+ Then run:
155
+
156
+ ```bash
157
+ bundle install
158
+ bundle exec analytics-ops setup \
159
+ --service-account ~/.config/analytics_ops/service-account.json
160
+ ```
161
+
162
+ Setup:
163
+
164
+ - validates the key
165
+ - verifies both Analytics APIs
166
+ - lists the GA4 properties the service account can access
167
+ - lets you choose a property
168
+ - creates `config/analytics_ops.yml`
169
+ - remembers only the key's absolute path in
170
+ `~/.config/analytics_ops/connection.json`
171
+
172
+ ### H. Verify the connection with read-only commands
42
173
 
43
- 4. Check access without changing anything:
174
+ ```bash
175
+ bundle exec analytics-ops doctor
176
+ bundle exec analytics-ops properties
177
+ bundle exec analytics-ops overview
178
+ bundle exec analytics-ops report traffic --json
179
+ bundle exec analytics-ops realtime
180
+ bundle exec analytics-ops audit
181
+ ```
182
+
183
+ Empty reports are normal for a new property. These checks are read-only in
184
+ GA4. Setup also makes no GA4 changes; it writes only the local configuration
185
+ and connection pointer.
186
+
187
+ `audit` exits with status `0` when configuration matches and status `2` when
188
+ it finds drift. Both are successful read-only results.
189
+
190
+ You do not need `gcloud`, a browser OAuth login, an OAuth consent screen, an
191
+ OAuth test-user list, or Gemini. An API key cannot authorize access to private
192
+ GA4 data.
193
+
194
+ `apply` is the mutating command. Do not run it until you have created and
195
+ reviewed a saved plan.
196
+
197
+ ### I. Quick troubleshooting
44
198
 
45
- ```bash
46
- bundle exec analytics-ops doctor
47
- bundle exec analytics-ops discover
48
- bundle exec analytics-ops audit
49
- bundle exec analytics-ops report traffic_acquisition
50
- ```
199
+ - **No properties listed:** Add the exact service-account email to the correct
200
+ GA4 account or property.
201
+ - **API disabled:** Select the correct Cloud project and confirm both
202
+ Analytics APIs are enabled.
203
+ - **Permission denied:** Grant Viewer or Editor inside GA4. A Google Cloud IAM
204
+ role does not grant access to GA4 data.
205
+ - **“This app is blocked” opens in a browser:** That is an obsolete OAuth
206
+ flow. Analytics Ops 0.2 uses a service-account JSON key and does not launch
207
+ browser authorization.
208
+ - **Key unavailable:** Run setup again with the key's new absolute path.
209
+ - **Key creation disabled:** An organization policy may prohibit downloaded
210
+ service-account keys. Ask the Google Workspace or Cloud administrator.
51
211
 
52
- Every command above is read-only. `audit` exits with status 2 when it finds
53
- drift, which makes it useful in CI.
212
+ Google's official guides cover
213
+ [GA4 account and property creation](https://support.google.com/analytics/answer/14183469?hl=en),
214
+ [Cloud project creation](https://docs.cloud.google.com/resource-manager/docs/creating-managing-projects),
215
+ [API enablement](https://docs.cloud.google.com/service-usage/docs/enable-disable),
216
+ [service-account creation](https://docs.cloud.google.com/iam/docs/service-accounts-create),
217
+ [JSON key creation](https://docs.cloud.google.com/iam/docs/keys-create-delete),
218
+ and [GA4 access management](https://support.google.com/analytics/answer/9305788?hl=en).
219
+
220
+ See the [live read-only smoke-test guide](docs/live-smoke-test.md) for a safe
221
+ real-app release test.
222
+
223
+ Already connected? List properties before creating configuration:
224
+
225
+ ```bash
226
+ analytics-ops properties
227
+ analytics-ops discover # includes data streams
228
+ ```
54
229
 
55
230
  ## The safe change workflow
56
231
 
@@ -81,8 +256,11 @@ what failed, and what remains.
81
256
 
82
257
  | Command | Purpose | Remote writes? |
83
258
  | --- | --- | --- |
259
+ | `analytics-ops setup --service-account PATH` | Connect, choose a property, and create minimal configuration | No |
260
+ | `analytics-ops properties` | List accessible accounts and properties without configuration | No |
84
261
  | `analytics-ops doctor` | Check configuration, credentials, APIs, property access, clients, and clock | No |
85
- | `analytics-ops discover` | List accessible accounts, properties, and streams | No |
262
+ | `analytics-ops discover` | List accessible accounts, properties, and streams without configuration | No |
263
+ | `analytics-ops overview` | Show five useful reports in one bounded batch | No |
86
264
  | `analytics-ops snapshot` | Print normalized managed remote state | No |
87
265
  | `analytics-ops audit` | Show drift without writing a plan file | No |
88
266
  | `analytics-ops plan --output FILE` | Review and save deterministic changes | No |
@@ -92,12 +270,16 @@ what failed, and what remains.
92
270
  | `analytics-ops realtime` | Run the realtime-events report | No |
93
271
  | `analytics-ops schema --format json` | Print the configuration schema | No |
94
272
 
95
- Use `--format json` for automation. CSV is available only for reports:
273
+ Use `--json` or `--format json` for automation. CSV is available only for
274
+ individual reports:
96
275
 
97
276
  ```bash
98
- bundle exec analytics-ops report landing_pages --format csv
277
+ bundle exec analytics-ops report landing-pages --csv
99
278
  ```
100
279
 
280
+ Friendly `traffic` and `landing-pages` aliases leave the original
281
+ `traffic_acquisition` and `landing_pages` names fully supported.
282
+
101
283
  See [Commands](docs/commands.md) for every option and exit status.
102
284
 
103
285
  ## IDs: the quick distinction
@@ -110,8 +292,8 @@ Use fake values like these in examples and tests:
110
292
  | Property ID | `123456789` | `property_id` in configuration and API requests |
111
293
  | Stream ID | `987654321` | `stream_id` in configuration |
112
294
  | Measurement ID | `G-EXAMPLE1` | Browser tagging; never use it as a stream ID |
113
- | OAuth client | A Cloud project client ID/secret | Owned by your application, never this YAML |
114
- | Service-account identity | `ga-reader@example-project.iam.gserviceaccount.com` | Granted GA access; its key is never this YAML |
295
+ | Cloud project | `example-analytics-project` | Owns enabled APIs, quota, and the service account |
296
+ | Service-account identity | `ga-reader@example-project.iam.gserviceaccount.com` | Granted GA4 access; its key is never this YAML |
115
297
 
116
298
  ## Ruby API
117
299
 
@@ -126,6 +308,9 @@ plan.write("tmp/ga4-plan.json")
126
308
 
127
309
  report = workspace.report("calculator_completions")
128
310
  report.rows.each { |row| puts row.fetch("eventCount") }
311
+
312
+ overview = workspace.overview
313
+ puts overview.report("overview_totals").rows
129
314
  ```
130
315
 
131
316
  Loading the gem, loading YAML, and booting Rails do not contact Google.
@@ -139,8 +324,12 @@ gem "analytics_ops", require: "analytics_ops/rails", group: :development
139
324
  ```
140
325
 
141
326
  ```bash
327
+ bundle exec analytics-ops setup \
328
+ --profile development \
329
+ --service-account /absolute/path/to/service-account.json
142
330
  bin/rails generate analytics_ops:install
143
331
  bin/rake analytics:doctor
332
+ bin/rake analytics:overview
144
333
  bin/rake 'analytics:report[traffic_acquisition]'
145
334
  ```
146
335
 
@@ -151,17 +340,19 @@ boot-time network calls. See [Rails integration](docs/rails.md).
151
340
  ## What Analytics Ops does not do
152
341
 
153
342
  - It does not inject browser analytics or manage consent banners.
154
- - It does not store credentials, tokens, report rows, or local state.
343
+ - It stores only the service-account key's path in a mode-`0600` user file;
344
+ it never copies the key, tokens, or report rows.
155
345
  - It does not delete accounts, properties, streams, or unmanaged resources.
156
346
  - It does not claim to manage settings that Google exposes only in the UI.
157
- - Experimental declarations are findings only in version 0.1.0; they are not
347
+ - Experimental declarations are findings only in version 0.2.0; they are not
158
348
  silently applied through Alpha APIs.
159
349
 
160
350
  ## Documentation
161
351
 
162
352
  | Guide | Topic |
163
353
  | --- | --- |
164
- | [Authentication](docs/authentication.md) | ADC, scopes, service accounts, and safe automation |
354
+ | [Authentication](docs/authentication.md) | One-time service-account setup and key safety |
355
+ | [Live smoke test](docs/live-smoke-test.md) | Real-app read-only verification and release gate |
165
356
  | [Configuration](docs/configuration.md) | Complete strict YAML contract |
166
357
  | [Commands](docs/commands.md) | CLI syntax, formats, and exit statuses |
167
358
  | [Reports](docs/reports.md) | Built-in recipes and GA reporting limitations |
data/SECURITY.md CHANGED
@@ -29,18 +29,18 @@ do not wait for a project response.
29
29
 
30
30
  Analytics Ops:
31
31
 
32
- - uses Application Default Credentials or an explicitly injected Google
33
- credential object
34
- - refuses credential-shaped configuration and plan fields
32
+ - uses only an explicit Google service-account key and never discovers
33
+ ambient credentials
34
+ - refuses credential-shaped configuration and plan fields or values
35
35
  - redacts common authorization material from translated errors
36
36
  - performs no network I/O while requiring the gem, loading YAML, or booting
37
37
  Rails
38
38
  - defaults to read-only commands
39
- - requires a strictly validated saved plan and explicit confirmation to mutate
39
+ - requires a strictly validated saved plan and literal boolean confirmation to mutate
40
40
  - rejects stale and cross-property plans
41
41
  - excludes delete/archive operations from ordinary plans
42
42
  - never logs report results automatically
43
- - has no telemetry, credential store, database, or browser injection
43
+ - has no telemetry, private-key/token store, database, or browser injection
44
44
  - publishes through RubyGems Trusted Publishing without a stored API key
45
45
 
46
46
  Plan files still describe operational configuration and are created with mode
@@ -51,6 +51,6 @@ under the operator's data policy.
51
51
 
52
52
  Analytics Ops cannot secure an overprivileged Cloud project, service account,
53
53
  GitHub organization, CI runner, GA property, or exported report. Use
54
- least-privilege read credentials for routine work, isolate mutation
55
- credentials, protect release environments, and keep production mutation
56
- credentials out of Rails web containers.
54
+ Viewer access when an installation only reports or audits; grant Editor only
55
+ when reviewed applies are required. Protect release environments and keep
56
+ production mutation credentials out of Rails web containers.
@@ -1,6 +1,6 @@
1
1
  # API support matrix
2
2
 
3
- This matrix describes Analytics Ops 0.1.0—not every method Google exposes.
3
+ This matrix describes Analytics Ops 0.2.0—not every method Google exposes.
4
4
 
5
5
  | State | Meaning |
6
6
  | --- | --- |
@@ -10,27 +10,28 @@ This matrix describes Analytics Ops 0.1.0—not every method Google exposes.
10
10
  | Manual | Reported as an operator checklist |
11
11
  | Unsupported | Deliberately outside the public contract |
12
12
 
13
- | Capability | State | Exact 0.1.0 behavior |
13
+ | Capability | State | Exact 0.2.0 behavior |
14
14
  | --- | --- | --- |
15
- | Account/property discovery | Audited | Lists accessible summaries |
16
- | Data-stream discovery | Audited | Lists web, Android, and iOS streams |
15
+ | Account/property discovery | Audited | Lists accessible summaries without requiring configuration |
16
+ | Data-stream discovery | Audited | Lists web, Android, and iOS streams without requiring configuration |
17
17
  | Web stream default URI | Managed | Updates an existing web stream |
18
18
  | Stream create/delete | Unsupported | Missing streams become findings |
19
19
  | Data retention | Managed | Reads and updates supported periods/reset behavior |
20
20
  | Key events | Managed | Reads and creates missing events; no delete |
21
21
  | Custom dimensions | Managed | Reads, creates, and updates display name/description; user ads flag where supported |
22
- | Custom metrics | Managed | Reads, creates, and updates display name/description |
22
+ | Custom metrics | Managed | Reads and creates with explicit currency-data classification; updates display name/description |
23
23
  | Standard Data API reports | Audited | Immutable definitions and normalized results |
24
24
  | Realtime Data API reports | Audited | Immutable definitions and normalized results |
25
- | Batch reports | Unsupported | Use individual definitions |
25
+ | Batched overview | Audited | Five bounded standard reports through one `batchRunReports` call |
26
+ | Friendly report aliases | Audited | `traffic` and `landing-pages` resolve to stable canonical recipes |
26
27
  | Enhanced Measurement | Experimental | Validated declaration and finding only; no mutation |
27
28
  | Google Signals | Experimental | Validated declaration and finding only; no mutation |
28
29
  | Consent coverage | Manual | Must be verified in tagging/consent systems |
29
30
  | Ads-personalization regions | Manual | Not inferred from similarly named API fields |
30
31
  | Stream data redaction | Manual | UI/API policy must be verified separately |
31
32
  | User-provided data setting | Unsupported | Not read or changed |
32
- | Event create/edit rules | Unsupported | Alpha, outside 0.1.0 |
33
- | Audiences and expanded datasets | Unsupported | Alpha, outside 0.1.0 |
33
+ | Event create/edit rules | Unsupported | Alpha, outside 0.2.0 |
34
+ | Audiences and expanded datasets | Unsupported | Alpha, outside 0.2.0 |
34
35
  | Google Ads, AdSense, DV360, SA360 links | Unsupported | Not read or changed |
35
36
  | BigQuery links | Unsupported | Not read or changed |
36
37
  | Access bindings | Unsupported | Not read or changed |
data/docs/architecture.md CHANGED
@@ -15,6 +15,12 @@ strict YAML
15
15
  immutable report definition
16
16
  → Data API adapter
17
17
  → immutable normalized result
18
+
19
+ configuration-free connection
20
+ → explicit service-account identity
21
+ → account/property discovery
22
+ → API access verification
23
+ → atomic minimal configuration
18
24
  ```
19
25
 
20
26
  ## Core objects
@@ -22,6 +28,7 @@ immutable report definition
22
28
  | Object | Responsibility |
23
29
  | --- | --- |
24
30
  | `Configuration` | Bounded safe YAML, environment interpolation, schema validation |
31
+ | `Configuration::Writer` | Non-destructive atomic creation of the smallest valid setup file |
25
32
  | `DesiredState` | Immutable configuration for one profile |
26
33
  | `Resources` | Gem-owned account/property/stream/settings values |
27
34
  | `Snapshot` | Canonical managed remote state and SHA-256 fingerprint |
@@ -31,6 +38,9 @@ immutable report definition
31
38
  | `Clients::Admin` | Official Admin request translation and response normalization |
32
39
  | `Reports::Definition` | Strict immutable Data API query |
33
40
  | `Clients::Data` | Standard/realtime request translation and result normalization |
41
+ | `ServiceAccount` | Strict JSON-key validation, scopes, and user-level path storage |
42
+ | `Connection` | Configuration-free discovery and selected-property access verification |
43
+ | `Setup` | Property selection, verification, and safe configuration creation |
34
44
  | `Workspace` | Public orchestration API with independently injectable clients |
35
45
  | `CLI` | Option validation, formats, stable statuses, and explicit confirmation |
36
46
  | `Railtie` | Optional generator and operator Rake tasks |
@@ -38,12 +48,14 @@ immutable report definition
38
48
  ## Dependency direction
39
49
 
40
50
  Domain and planning code know nothing about protobufs, gRPC, Rails, Active
41
- Support, OAuth flows, or HTTP transports. Admin and Data adapters translate
51
+ Support, authentication flows, or HTTP transports. Admin and Data adapters translate
42
52
  official generated values immediately into immutable Analytics Ops values.
43
53
  The adapters can be injected independently, so tests use deterministic fakes.
44
54
 
45
- The core requires Google's wrapper gems lazily. Requiring `analytics_ops`
46
- defines classes only; it does not instantiate a client or discover ADC.
55
+ The core requires Google's wrapper gems lazily. Requiring `analytics_ops`,
56
+ constructing a `Connection`, loading configuration, and booting Rails define
57
+ or validate local objects only; they do not instantiate a generated client,
58
+ read a service-account key, or contact Google.
47
59
 
48
60
  ## State model
49
61
 
@@ -52,6 +64,12 @@ database. The configuration declares desired state and a snapshot captures the
52
64
  relevant remote state. Canonical key ordering and normalized arrays make
53
65
  snapshot fingerprints and plan bytes deterministic.
54
66
 
67
+ `setup` discovers properties through a configuration-free `Connection`,
68
+ verifies the selected property, and creates the existing versioned YAML
69
+ format. Existing conflicting configuration is never rewritten. A separate
70
+ user-level `connection.json` stores only the absolute service-account key
71
+ path. It is not desired state and contains no key material.
72
+
55
73
  Apply accepts an already validated plan, refreshes the snapshot, compares its
56
74
  fingerprint, then sends only the saved operations. A partial response is
57
75
  explicit reconciliation data, not a hidden retry or rollback.
@@ -83,7 +101,7 @@ call. Browser analytics and consent remain application concerns.
83
101
 
84
102
  ## Experimental boundary
85
103
 
86
- Google identifies certain Admin capabilities as Alpha. Version 0.1.0 accepts
104
+ Google identifies certain Admin capabilities as Alpha. Version 0.2.0 accepts
87
105
  explicit Enhanced Measurement and Google Signals declarations only so they can
88
106
  appear as experimental findings. It does not apply them. Stable/beta
89
107
  operations do not depend on an experimental public Analytics Ops contract.