Scope
- Platform: BigQuery
- Scope: projects lab-a (data); regions EU, europe-west1, US
- Privilege level: 2 (+ queries (normalized forms), reads per table, policies)
- SQL mode: read-only
- Reads: 18 done out of 22
- Content read: 9 tables, 12 objects, 3 query families
- Hidden schemas or datasets read: _tmp
- Versions: canot 0.1.0, duckdb 1.5.6, sqlglot 30.22.0
Capabilities
This report is an inventory: inventoried, neither exported nor replayed.
| Level | This report | Canot on BigQuery |
|---|---|---|
| Inventory | done by this scan (level 2) | full, levels 1 to 3 |
| Export | not done by this scan | iceberg, with canot drill |
| Evidence | not done by this scan | P1 data parity; P2 query replay, with canot drill |
BigQuery connector: tested; recorded test: canot drill, 2026-10-13: public dataset thelook_ecommerce (docs/ecarts.md).
What Canot cannot prove here: the declared forms (P1, P2) cover tables and queries; objects to rebuild besides tables are counted, not proven.
Observed costs
Window: 180 days. On-demand and reserved: two billing models, never added together.
On demand
| Item | Value | Nature and basis |
|---|---|---|
| Billed bytes | 3.8 TB | measured · B10, B11, B12 |
| Queries | 1,200 queries | measured · B10, B11, B12 |
| In dollars | $0.00 to $21.88
| estimated, low confidence · B10, B11, B12 billed TiB × list price, free tier deducted or not |
Reserved
| Item | Value | Nature and basis |
|---|---|---|
| Slot-hours | 820.5 slot-hours | measured · B10, B11, B12 |
| Queries | 300 queries | measured · B10, B11, B12 |
| In dollars | Not estimated: your contract price not read. | not estimated |
On demand and reserved do not add up: two billing models, two bases.
Storage
| Item | Value | Nature and basis |
|---|---|---|
| Average billed storage | Not read: not provided by collection. | not read |
| Storage in dollars | Not estimated: your contract price not read. | not estimated |
Movements
2 frozen, 7 live, 0 recreated, 0 not determined.
recreated: DDL less than 7 days old with no later write; live: write less than 30 days old; frozen: older last write; not determined: writes not read. Based on: B03, B04, B05, B07, B10, B11 ….
| Table | Type | Volume | Movement | Evidence |
|---|---|---|---|---|
| lab-a.archive.archive_2023 | TABLE | 3 GB | frozen | last write on 2025-03-01 |
| lab-a.raw.orders | TABLE | 900 MB | live | last write on 2026-10-15 |
| lab-a.raw.read_by_api_only | TABLE | 700 MB | frozen | last write on 2026-09-01 |
| lab-a.raw.customers | TABLE | 200 MB | live | last write on 2026-10-15 |
| lab-a.raw.events_20261001 | TABLE | 120 MB | live | last write on 2026-10-15 |
| lab-a._tmp.scratch | TABLE | 50 MB | live | last write on 2026-10-15 |
| lab-a.raw.orders_snap | SNAPSHOT | 10 MB | live | last write on 2026-10-15 |
| lab-a.ext.gcs_events | EXTERNAL | not read | live | last write on 2026-10-15 |
| lab-a.ext.sheet_targets | EXTERNAL | not read | live | last write on 2026-10-15 |
What does not leave with the copy
Objects to rebuild or describe
| Type | Count | Examples |
|---|---|---|
| function | 1 | lab-a.mart.js_clean |
| ML model | 1 | lab-a.ml.churn |
| share | 1 | lab-a.hub.listing_sales |
| row access policy | 1 | lab-a.raw.rap_country |
| procedure | 1 | lab-a.mart.sp_rebuild |
| scheduled query | 4 | lab-a.sq_daily_kpi, lab-a.sq_export, lab-a.sq_old, lab-a.sq_weekly |
| view | 2 | lab-a.mart.v_legacy, lab-a.mart.v_sheet |
| materialized view | 1 | lab-a.mart.mv_daily |
Routines per language: JAVASCRIPT 1, SQL 1.
Columns with a platform-specific type (3)
| Table | Column | Type |
|---|---|---|
| lab-a.raw.customers | geo | GEOGRAPHY |
| lab-a.raw.events_20261001 | payload | JSON |
| lab-a.raw.events_20261001 | ctx | STRUCT<a INT64, b STRING> |
Billed history
| Item | Value | Nature and basis |
|---|---|---|
| Time Travel and Fail-safe (1 table) | 250 MB | computed · B07 Time Travel + Fail-safe of present tables, + bytes still billed for dropped tables |
Dependencies
External dependencies (F01)
| Object | Type | Location |
|---|---|---|
| lab-a.ext.gcs_events | table | gs://lab-bucket |
| lab-a.ext.sheet_targets | table | docs.google.com |
Hidden external dependencies (F02)
| Object | Path | Location |
|---|---|---|
| lab-a.mart.v_sheet | lab-a.mart.v_sheet → lab-a.ext.sheet_targets | docs.google.com |
Writes outside the platform (F03)
| Source | Mode | Destination |
|---|---|---|
| family 333333333333 | observed | gs://lab-exports |
| object lab-a.sq_export | declared | gs://lab-exports |
External consumers (F09)
| Share | Accounts |
|---|---|
| lab-a.hub.listing_sales | 1 |
Tools seen in queries
| Tool | Families | Executions |
|---|---|---|
| looker | 1 | 900 |
| scheduled_query | 1 | 180 |
| notebook | 1 | 40 |
Query replayability
| Category | Meaning | Families | Executions | Weight |
|---|---|---|---|---|
| C0 | translated and accepted by DuckDB | 1 | 900 | 2 TB |
| C1 | not parseable | 0 | 0 | 0 B |
| C2 | command, not analyzed | 0 | 0 | 0 B |
| C3 | translation impossible | 0 | 0 | 0 B |
| C4 | DuckDB parse error | 1 | 40 | 500 GB |
| C5 | binding error (platform-specific object or function) | 0 | 0 | 0 B |
| C6 | variable | 0 | 0 | 0 B |
| C7 | DDL, COPY, MERGE, metadata queries: counted separately | 1 | 180 | 10 GB |
| Item | Value | Nature and basis |
|---|---|---|
| C0 rate, by families | 50.0% | computed · B10, B11, B12 C0 ÷ C0 to C6, in families; C7 counted separately |
| C0 rate, by executions | 95.7% | computed · B10, B11, B12 C0 ÷ C0 to C6, in executions; C7 counted separately |
| C0 rate, weighted | 80.0% | computed · B10, B11, B12 C0 ÷ C0 to C6, in bytes; C7 counted separately |
Based on: 3/3 families, from 2026-04-20 to 2026-10-17, sqlglot 30.22.0, duckdb 1.5.6.
accepted ≠ identical result. Translated to DuckDB, not compared.
Most executed families (normalized forms)
| Category | Executions | Tool | Normalized form |
|---|---|---|---|
| C0 | 900 | looker | SELECT * FROM `lab-a.raw.orders` WHERE d >= ? |
| C7 | 180 | scheduled_query | EXPORT DATA OPTIONS (uri = ?, format = ?) AS SELECT * FROM `lab-a.mart.kpi` |
| C4 | 40 | notebook | SELECT * FROM `lab-a.raw.events_*` WHERE _TABLE_SUFFIX = ? |
Ranges
Planning estimates: each range carries its assumptions. A canot drill replaces the assumed throughput with a measurement.
| Item | Value | Nature and basis |
|---|---|---|
| Volume to copy | 5 GB
| computed · B07 sum of active bytes |
| Copy read time | 1 min to 4 min
| estimated, low confidence · B07 volume ÷ assumed throughput |
| Copy read cost | Not estimated: your contract price not read.
| not estimated |
| Rework | 3.0 d to 18.0 d
| estimated, low confidence · B13, B19, B20 objects × days per object + columns × days per column |
Findings
Each finding is labeled "To review", with no severity level. It states what is observed and what is not.
F01 · External dependencyTo review
2 findings
| Target | Observed |
|---|---|
| table lab-a.ext.gcs_events | External table: data outside the platform (gs://lab-bucket). |
| table lab-a.ext.sheet_targets | External table: data outside the platform (docs.google.com). |
F02 · Hidden external dependencyTo review
1 finding
| Target | Observed |
|---|---|
| object lab-a.mart.v_sheet | Depends on lab-a.ext.sheet_targets, outside the platform, through 1 level: lab-a.mart.v_sheet → lab-a.ext.sheet_targets (docs.google.com). |
F03 · Write outside the platformTo review
2 findings
| Target | Observed |
|---|---|
| family 333333333333 | Write outside the platform observed: 180 executions (scheduled_query); destination: gs://lab-exports. |
| object lab-a.sq_export | Scheduled query that writes outside the platform (declared in its definition); destination: gs://lab-exports. |
F05 · Storage with no observed readTo review
2 findings
| Target | Observed |
|---|---|
| table lab-a.archive.archive_2023 | 3 GB stored. No read observed in INFORMATION_SCHEMA.JOBS from 2026-04-20 to 2026-10-17; blind spots: reads through the Storage Read API, queries run from other projects, Analytics Hub consumers. |
| table lab-a.raw.read_by_api_only | 700 MB stored. No read observed in INFORMATION_SCHEMA.JOBS from 2026-04-20 to 2026-10-17; blind spots: reads through the Storage Read API, queries run from other projects, Analytics Hub consumers. |
F06 · Billed history that does not transferTo review
1 finding
| Target | Observed |
|---|---|
| table lab-a.raw.orders | 250 MB of billed history (Time Travel and Fail-safe), retention 7 days, for 900 MB active; this history does not leave with the copy. |
F08 · Dynamic SQLTo review
1 finding
| Target | Observed |
|---|---|
| object lab-a.mart.sp_rebuild | Procedure (SQL): builds SQL at run time; the objects it touches cannot be read from the code. |
F09 · External consumersTo review
1 finding
| Target | Observed |
|---|---|
| object lab-a.hub.listing_sales | Share to 1 subscriber; 1 shared object. Consumer reads are not seen by this scan. |
F10 · Security to rebuildTo review
2 findings
| Target | Observed |
|---|---|
| object lab-a.raw.rap_country | Row access policy applied to 1 object; it does not leave with the copy; the copy requires an unfiltered principal. |
| table lab-a.raw.customers | Policies: pt-pii, rap_country. They do not leave with the copy; the copy requires a principal not filtered by these policies. |
F11 · Scheduled chain and its failuresTo review
4 findings
| Target | Observed |
|---|---|
| object lab-a.sq_daily_kpi | Scheduled query, schedule every 24 hours, state active; 180 runs, 3 failures, last on 2026-10-17. |
| object lab-a.sq_export | Scheduled query, schedule every day 05:00, state active; 180 runs, 0 failures. |
| object lab-a.sq_old | Scheduled query, schedule every 1 hours, state disabled; 0 runs, 0 failures. |
| object lab-a.sq_weekly | Scheduled query, schedule every monday 06:00, state active; 26 runs, 0 failures. |
F12 · Incomplete readTo review
3 findings
| Target | Observed |
|---|---|
| read B15 | API connections.list not read (missing privilege); limits: external connections (F01). |
| read B18 | `region-eu`.INFORMATION_SCHEMA.RESERVATIONS not read (privilege level not requested); limits: reserved capacity. |
| read B22 | `region-eu`.INFORMATION_SCHEMA.JOBS_BY_ORGANIZATION not read (privilege level not requested); limits: queries run from other projects. |
No finding for: F04, F07. An absence of findings only holds for the reads done (see F12 and the method).
What this report does not quantify
- Average billed storage: not provided by collection.
- Storage cost: your contract price not read.
- Reserved, in dollars: your contract price not read.
- Copy read cost (Storage Read API, network egress): your contract price not read.
- Your contract rate: your contract price not read.
- Destination storage, running both platforms in parallel, operations after the exit: depend on your contract and your architecture.
- Identical results of translated queries: accepted ≠ identical result: translated to DuckDB, not compared; a canot drill compares the results.
- Cost projections provided by the platform: not used: they cannot be verified from the scan.
- BigQuery free tier: shared by the billing account, cannot be attributed per project.
- Reads through the Storage Read API: missing from INFORMATION_SCHEMA.JOBS.
- Billed bytes of queries under a row access policy: NULL value in INFORMATION_SCHEMA.JOBS.
Using this report for GDPR, DORA, the Data Act and SecNumCloud
These elements can support your own work on GDPR, DORA, the Data Act or SecNumCloud. They are evidence, not a finding: this report is not a certification, it is not legal advice, and it does not say whether your contracts or your organization meet any regulation.
| Framework | What it asks, in short | What this report gives you | What it does not cover |
|---|---|---|---|
| DORA (Regulation (EU) 2022/2554) | Art. 28(8) and 30(3)(f): a realistic transition, with an adequate period. | Measured throughput and a recovery time range from the exercise; a copy duration range (estimated) in the scan. | Excludes human validation and the cutover of your applications. |
| DORA (Regulation (EU) 2022/2554) | Art. 28: knowing what depends on the ICT provider. | What does not move as is: views, routines, tasks, policies, external dependencies, with the evidence behind each finding. | An inventory of the platform, not of your contracts or of the applications connected to it. |
| Data Act (Regulation (EU) 2023/2854) | Art. 29: switching charges are withdrawn from 12 January 2027. | The effort that remains yours: read cost, copy duration and rework estimates, each marked measured, computed or estimated. | Says nothing about charges your provider may still apply before that date. Prices are dated catalogue figures, not your contract. |
| GDPR (Regulation (EU) 2016/679) | Chapter V (transfers) and Art. 32 (security of processing). | Where the copy is hosted, and which security objects do not move with it (masking and row policies, tags). | The hosting location is the destination you chose. The legal assessment of a transfer is yours. |
| GDPR (Regulation (EU) 2016/679) | Art. 5(1)(c): data minimisation. | The scan reads metadata and execution history, not table contents. SQL text is masked and identities are pseudonymised. | Applies to the scan only: an exit exercise (drill) reads the data it copies. |
References as of 2026-10-19. Check the current texts: they evolve, and their application depends on your situation.
Method
18 reads done out of 22. Each read is recorded with its status and its reason; a value that was not read stays empty, never 0.
| Id | View | Status | Reason | Rows | Window | Latency |
|---|---|---|---|---|---|---|
| B06 | `region-eu`.INFORMATION_SCHEMA.TABLE_STORAGE | not read | absent or not exposed; limits: none: tables.get read instead | not read | ||
| B15 | API connections.list | not read | missing privilege; limits: external connections (F01) | not read | ||
| B18 | `region-eu`.INFORMATION_SCHEMA.RESERVATIONS | not read | privilege level not requested; limits: reserved capacity | not read | ||
| B22 | `region-eu`.INFORMATION_SCHEMA.JOBS_BY_ORGANIZATION | not read | privilege level not requested; limits: queries run from other projects | not read | ||
| B01 | API datasets.list | read | 10 | |||
| B02 | API datasets.get | read | 10 | |||
| B03 | `region-eu`.INFORMATION_SCHEMA.TABLES | read | 10 | |||
| B04 | `region-europe-west1`.INFORMATION_SCHEMA.TABLES | read | 10 | |||
| B05 | `region-us`.INFORMATION_SCHEMA.TABLES | read | 10 | |||
| B07 | API tables.get | read | 10 | |||
| B08 | `region-eu`.INFORMATION_SCHEMA.TABLE_OPTIONS | read | 10 | |||
| B09 | `region-eu`.INFORMATION_SCHEMA.COLUMN_FIELD_PATHS | read | 10 | |||
| B10 | `region-eu`.INFORMATION_SCHEMA.JOBS | read | 10 | from 2026-04-20 to 2026-10-17 | 0.1 h | |
| B11 | `region-europe-west1`.INFORMATION_SCHEMA.JOBS | read | 10 | from 2026-04-20 to 2026-10-17 | 0.1 h | |
| B12 | `region-us`.INFORMATION_SCHEMA.JOBS | read | 10 | from 2026-04-20 to 2026-10-17 | 0.1 h | |
| B13 | API transferConfigs.list | read | 10 | |||
| B14 | API rowAccessPolicies.list | read | 10 | |||
| B16 | `region-eu`.INFORMATION_SCHEMA.SCHEMATA_LINKS | read | 10 | |||
| B17 | `region-eu`.INFORMATION_SCHEMA.SHARED_DATASET_USAGE | read | 10 | |||
| B19 | `region-eu`.INFORMATION_SCHEMA.ROUTINES | read | 10 |
… and 2 more in reads.csv.
Privileges used
Level 2: bigquery.jobs.create, jobs.listAll, datasets.get, tables.list, tables.get, routines.list, routines.get, models.list, models.getMetadata, rowAccessPolicies.list, transfers.get, connections.list, dataPolicies.list (optional). Never requested: tables.getData, bigquery.user and jobUser roles.
Cost of the scan
| Item | Value | Nature and basis |
|---|---|---|
| Queries sent | 20 queries
| computed · B01, B02, B03, B04, B05, B06 … reads attempted, read or refused by the platform |
| Read time | Not read: duration not provided by collection. | not read |
Safeguards
- Every SQL statement sent goes through a read-only guard: only SELECT, SHOW, DESCRIBE and ALTER SESSION SET statements go out. No write, no API activation, no parameter change.
- Query users and roles pseudonymized with HMAC, using a salt drawn for this scan and never written; tag values hashed; locations reduced to the bucket.
- Raw SQL text is never written: only normalized forms, with literals masked, leave collection.
Rules
- Movement: recreated: DDL less than 7 days old with no later write; live: write less than 30 days old; frozen: older last write; not determined: writes not read.
- Storage with no read: actual window of the view read, compared with 180 days; the blind spots of each view are listed in the finding.
- Copy time: assumed throughput of 20 to 80 MB/s.
- List prices are dated and sourced; they do not replace your contract price.
Next steps
This report describes your platform; it recommends neither leaving nor staying.
To measure an exit on a chosen scope: canot drill copies to Apache Iceberg, compares source and copy, and signs an evidence report.
To go further, the q4o assessment, from €22,000 excl. VAT: your contract rate, actual execution, scenarios, the steps to follow. canot.io