# What does google_drive.permission.granted prove?

> Prove that Drive gave the intended person the intended access to the file. Version 1.0.0, certification Provisional.

Canonical: https://provely.sh/verify/google_drive/google_drive.permission.granted  
Last reviewed: 2026-09-05  
Skill version: 0.1.0  
Certification: provisional  

**Prove that Drive gave the intended person the intended access to the file. A permission that exists is not a permission for the right person. This level reads the address, the type and the role of the grantee.**

*Contract identity.*

| Fact | Value |
| --- | --- |
| Contract id | `google_drive.permission.granted` |
| Version | `1.0.0` |
| Hash | `6f5913fa8e69c56b` |
| Completion level | `granted` |
| Publisher | Built and signed by Provely. |
| Certification | Provisional |
| Skill | [Google Drive API 0.1.0](/verify/google_drive) |
| Valid for provider API versions | `v3.20260901` |

## What is the intent?

Give the person the stated role on the file.

## What is the subject and the action?

| Member | Value |
| --- | --- |
| Subject type | `google_drive.permission` |
| Subject identity | permission_id = `$action.result.id` |
| Canonical effect | `access.permission_grant` |
| Provider operation | `POST /drive/v3/files/{fileId}/permissions` |
| Idempotency | none, retry is not safe |

## How does the evidence correlate with this operation?

| Strategy | Assurance | Keys | Required |
| --- | --- | --- | --- |
| `resource_id` | strong | permission_id from `$action.result.id` | no |
| `resource_id` | weak | file_id from `$input.file_id` | no |
| `fingerprint` | weak | file_id from `$input.file_id`; grantee_email from `$input.grantee_email` | no |

## Which evidence does the contract require?

Minimum evidence level `E2`. An independent channel is required. Minimum channels: 1.

| Channel | Level | Independence | Verifier | Description |
| --- | --- | --- | --- | --- |
| `permission_readback` | E2 | provider readback | `http` | Read one permission of the file. A condition path is $observed.permission_readback.emailAddress. The read states the fields parameter, because a default read carries no grantee. |
| `permission_change_events` | E3 | provider event | `webhook` | The notifications of a channel that watches the file, since the operation started. The webhook verifier returns {events, count, latest, earliest, types, duplicates_dropped}. A Drive notification carries an empty body, so a count states how many times the list changed. |

## Which conditions must all hold for VERIFIED?

| Condition | Meaning | Path | Operator | Expected | Evidence |
| --- | --- | --- | --- | --- | --- |
| `permission_change_event` | At least one notification says that the permissions of the file changed since the operation started. The Permission resource carries no creation time, so this channel is the one evidence that ties the grant to this operation. | `$observed.permission_change_events.count` | `gte` | `1` | `permission_change_events` |

## Which conditions give CONTRADICTED?

| Condition | Class | Reason | Path | Operator | Expected |
| --- | --- | --- | --- | --- | --- |
| `permission_identity_differs` | wrong subject | The provider holds another permission than the answer named. | `$observed.permission_readback.id` | `ne` | `$action.result.id` |
| `permission_grantee_differs` | wrong subject | The permission grants access to a different person than the intent named. | `$observed.permission_readback.emailAddress` | `ne` | `$input.grantee_email` |
| `permission_role_differs` | wrong subject | The permission grants a different role than the intent named. | `$observed.permission_readback.role` | `ne` | `$input.role` |
| `permission_type_differs` | wrong subject | The permission names a different scope than the intent named. A grant to a domain or to anyone reaches more people than the person asked for. | `$observed.permission_readback.type` | `ne` | `$input.grantee_type` |
| `permission_inherited_from_parent` | other | The permission comes from a parent folder. This operation did not make it, and nobody can remove it on this item. | `$observed.permission_readback.permissionDetails[0].inherited` | `eq` | `true` |
| `permission_grantee_account_deleted` | other | The account behind the permission was deleted. Nobody received the access. | `$observed.permission_readback.deleted` | `eq` | `true` |
| `permission_notification_predates_operation` | pre existing state | The access control list changed before the operation started. That change proves nothing about this operation. | `$observed.permission_change_events.earliest.provider_timestamp` | `time_before` | `$operation.created_at` |
| `duplicate_permission_grant` | duplicate side effect | The access control list of the file changed more than once since the operation started. Stop and ask a person. | `$observed.permission_change_events.count` | `gt` | `1` |

## Which observed states map to a verdict before completion?

| Rule | Match | Verdict | Reason |
| --- | --- | --- | --- |
| `ownership_not_accepted` | `$observed.permission_readback.pendingOwner` eq `true` | PENDING | The grantee has not accepted the transfer of ownership. |
| `permission_inside_a_view` | `$observed.permission_readback.view` eq `"published"` | CONTRADICTED | The permission belongs to the published view, and Drive then states the role publishedReader. No published role list names that role. Ask a person. |

## How long does the runtime observe?

| Timing member | Value |
| --- | --- |
| Initial delay | 1000 ms |
| Poll interval | 5000 ms |
| Backoff | exponential factor 2, max 60000 ms |
| Maximum attempts | 40 |
| Timeout | 900000 ms |
| Stale read window | 20000 ms |
| On timeout | UNVERIFIABLE (`evidence_unavailable_before_timeout`), escalated to a person |

## Where do these rules come from?

- `google_drive.openapi#/paths/~1drive~1v3~1files~1{fileId}~1permissions/post`: [google_drive.openapi](https://www.googleapis.com/discovery/v1/apis/drive/v3/rest), retrieved 2026-09-09
- `google_drive.openapi#/paths/~1drive~1v3~1files~1{fileId}~1permissions/post/responses/200`: [google_drive.openapi](https://www.googleapis.com/discovery/v1/apis/drive/v3/rest), retrieved 2026-09-09
- `google_drive.docs.sharing#share-files-folders-and-drives/create-a-permission`: [google_drive.docs.sharing](https://developers.google.com/workspace/drive/api/guides/manage-sharing), retrieved 2026-09-09
- `google_drive.docs.sharing#share-files-folders-and-drives/a-response-returns-a-subset-of-the-members`: [google_drive.docs.sharing](https://developers.google.com/workspace/drive/api/guides/manage-sharing), retrieved 2026-09-09
- `google_drive.events#/events/drive.file.update.permissions`: [google_drive.events](https://developers.google.com/workspace/drive/api/guides/push), retrieved 2026-09-09
- `google_drive.docs.push#push-notifications/the-changed-members`: [google_drive.docs.push](https://developers.google.com/workspace/drive/api/guides/push), retrieved 2026-09-09
- `google_drive.openapi#/paths/~1drive~1v3~1files~1{fileId}~1watch/post`: [google_drive.openapi](https://www.googleapis.com/discovery/v1/apis/drive/v3/rest), retrieved 2026-09-09

### Can google_drive.permission.granted return VERIFIED from the action response alone?

No. The minimum evidence level is E2. The action response is E1. The completion conditions read `permission_change_events`.

### What happens after the timeout?

The verdict is UNVERIFIABLE with the reason `evidence_unavailable_before_timeout`. The operation goes to a person for review.

## Read next

- [Read the Google Drive API verification page](https://provely.sh/verify/google_drive)
- [Read the google_drive.file.content_stored contract](https://provely.sh/verify/google_drive/google_drive.file.content_stored)
- [Read the google_drive.file.created contract](https://provely.sh/verify/google_drive/google_drive.file.created)
- [Read what a completion contract contains](https://provely.sh/contracts)
- [Read what a receipt proves](https://provely.sh/docs/receipts)
