Scope
- Platform: BigQuery
- Scope: projects lab-a (data); regions EU, europe-west1, US
- Privilege level: 3 (+ privileges and tools (pseudonymized))
- SQL mode: read-only
- Reads: 18 done out of 22
- Content read: 9 tables, 12 objects, 4 query families
- Hidden schemas or datasets read: _tmp
- Versions: canot X, duckdb X, sqlglot X
Capabilities
This report is an inventory: inventoried, neither exported nor replayed.
| Level | This report | Canot on BigQuery |
|---|---|---|
| Inventory | done by this scan (level 3) | 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 066b5f1f3a39 | observed | gs://bucket-x |
| 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 |
|---|---|---|
| unidentified | 3 | 903 |
| looker | 1 | 10 |
Query replayability
| Category | Meaning | Families | Executions | Weight |
|---|---|---|---|---|
| C0 | translated and accepted by DuckDB | 1 | 10 | 1 MB |
| 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 | 1 | not read |
| C5 | binding error (platform-specific object or function) | 1 | 900 | 2 TB |
| C6 | variable | 0 | 0 | 0 B |
| C7 | DDL, COPY, MERGE, metadata queries: counted separately | 1 | 2 | 50 kB |
| Item | Value | Nature and basis |
|---|---|---|
| C0 rate, by families | 33.3% | computed · B10, B11, B12 translated and accepted by DuckDB (C0) / C0 to C6; C7 counted separately |
| C0 rate, by executions | 1.1% | computed · B10, B11, B12 translated and accepted by DuckDB (C0) / C0 to C6; C7 counted separately |
| C0 rate, weighted | 0.0%
| computed · B10, B11, B12 translated and accepted by DuckDB (C0) / C0 to C6; C7 counted separately |
Based on: 1/3 families, window not read, sqlglot X, duckdb X.
accepted ≠ identical result. Translated to DuckDB, not compared.
1 family containing a secret, counted then set aside.
Platform-specific functions
| Function | Families |
|---|---|
| predict | 1 |
Most executed families (normalized forms)
| Category | Executions | Tool | Normalized form |
|---|---|---|---|
| C5 | 900 | SELECT * FROM `lab-a.raw.orders` WHERE d >= ? | |
| C0 | 10 | looker | SELECT count(*) FROM `lab-a.raw.customers` |
| C7 | 2 | EXPORT DATA OPTIONS (uri=?, FORMAT=?) AS SELECT * FROM `lab-a.raw.orders` | |
| C4 | 1 | SELECT ML.PREDICT(MODEL `lab-a.raw.m`, (SELECT ?)) |
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 066b5f1f3a39 | Write outside the platform observed: 2 executions; destination: gs://bucket-x. |
| 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.
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 3: 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), reservations.list, reservationAssignments.list, capacityCommitments.list, organization-level permissions. 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