Skip to main content

DriveOperation

Enum DriveOperation 

Source
pub enum DriveOperation {
    Read,
    Create,
    Upload,
    Edit,
    SheetsWrite,
    SheetsStructure,
    SheetsDelete,
    SheetsProtection,
    DocsWrite,
}
Expand description

A Drive operation this gate can permit or refuse. Reused directly as the settings-file rule shape (crate::utils::settings::WritePermissionsSettings) — no separate wire type.

Variants§

§

Read

List/read/export/download.

§

Create

Create a new file or folder.

§

Upload

Upload local content into a new file.

§

Edit

Replace an existing file’s content.

§

SheetsWrite

Write cells into an existing Google Sheet via the Sheets API (issue #1589, ADR-0073 §3).

Deliberately not folded into Self::Edit. Every existing allow: ["edit"] rule was written when drive edit refused every Google-native document outright, so reusing Edit here would retroactively upgrade those rules into cell-write permission with no config change and no re-consent — the exact silent widening this gate’s default-deny posture exists to prevent.

Since issue #1798 (ADR-0081 §5), also required (alongside Self::SheetsStructure) for add-pivot-table — a pivot table is created by updateCells, writing through the grid with a server-computed rendered extent, which is this operation’s territory by construction. delete-pivot-table needs this operation alone.

Since issue #1839 (ADR-0083 §4), also the clipboard-style paste family — cut-paste/copy-paste with a value-only --paste-type (values/formula) and paste-data‘s values/formula types — since each writes ordinary cell content into a range this crate already lets sheets clear/write reach. cut-paste additionally requires Self::SheetsStructure whatever --paste-type names, since it always clears its source’s formats and merges too; copy-paste/paste-data require it alongside this operation only for --paste-type normal, per that variant’s doc comment. Since issue #1840 (ADR-0083 §1), also covers auto-fill (autoFill) alone: it writes ordinary cell content into a range the request names or derives, exactly what this operation already permits via sheets clear followed by sheets write of the same range. Provisional on ADR-0083 §5’s live-verification rule — if a fill is found to carry the source cells’ formatting, auto-fill moves to the two-operation composition add-pivot-table uses, alongside Self::SheetsStructure.

Since issue #1841 (ADR-0083 §1), also required for find-replace. Its range, sheet and all-sheets scopes replace only cell values or formulas, already covered by sheets write and sheets clear; scope does not create a new permission boundary within a spreadsheet.

Since issue #1842 (ADR-0083 §3), also one half of sort-range’s gate, alongside Self::SheetsStructure — re-gated by issue #1870 after live verification found a sorted row carries its formatting, notes and data-validation rules with it (see that variant’s doc comment). It shipped first on this operation alone, on a values-only reading: it permutes values within a caller-named range, which a sheets-write grant could already replace or clear.

Since issue #1843 (ADR-0083 §1), also one half of text-to-columns’ gate, for the cell content the split writes — but not the whole of it. ADR-0083 §1 proposed this operation alone and §5 made that provisional on live verification; the live run found a split carries the source cell’s formatting into the spill cells, so §5’s fixed consequence applies and text-to-columns needs Self::SheetsStructure too, the two-operation composition add-pivot-table uses.

Since issue #1845 (ADR-0083 §§3, 5), also one half of randomize-range’s gate, alongside Self::SheetsStructure, for the cell values a reorder permutes. ADR-0083 §3 proposed this operation alone and §5 made that provisional on live verification, same as text-to-columns; the live run found a reordered row carries its formatting, notes and data-validation rules with it, so §5’s fixed consequence applies here too.

Since issue #1940, also one half of set-basic-filter --sort-by’s gate, alongside Self::SheetsStructure: a basic filter’s sort is applied by physically reordering the rows, the same permutation as randomize-range, so it takes the same union (see that variant’s doc comment).

Since issue #1844 (ADR-0083 §1), also trim-whitespace: it rewrites cell content in place, which a sheets write of the same range could already replace outright. Unlike the reorder verbs above, it stays on this operation alone: issue #1877’s live check found a trim moves no formatting, and even rebases rich-text runs to keep them on the characters that remain. Its sibling verb in that issue, delete-duplicates, takes Self::SheetsDelete instead — two verbs shipped together under two different operations, which is the per-verb mapping working as intended, not a special case.

§

SheetsStructure

Structurally edit an existing Google Sheet via spreadsheets.batchUpdate (issue #1613, ADR-0075 §1) — adding, renaming and inserting rows or columns; since issue #1643 (ADR-0078), cell/border formatting, merging, auto-resize, column width/row height, data validation, duplicateSheet, and sheet reorder/hide. Since issue #1795 (ADR-0081 §4), also developer-metadata management (set-developer-metadata/delete-developer-metadata), restricted to DOCUMENT visibility — PROJECT-visibility metadata, which belongs to a different OAuth client, is never reachable through this surface; since issue #1793 (ADR-0081 §1), conditional formatting (add-conditional-format/update-conditional-format/ delete-conditional-format); since issue #1796 (ADR-0081 §2), also named-range add/update/delete: a named range is a label over a region, not grid data, so removing one leaves every cell’s stored value and formula text untouched — even though every cell formula referencing the removed name starts evaluating to #REF!. That visible-but-not-destructive effect is mitigated, not by a stronger gate, but by delete-named-range scanning the workbook’s cell formulas for the name and reporting the count and A1 locations of every reference before it deletes, in both --dry-run and the real run; and, since issue #1797 (ADR-0081 §3), charts and slicers (add-chart/update-chart/delete-chart/add-slicer/ update-slicer/delete-slicer) — including the two deletes, which destroy an unrecoverable embedded object rather than grid data, and so join this operation (not Self::SheetsDelete) on the same “property of the sheet, not the sheet’s data” reasoning as unmerge-cells/clear-data-validation. None of that later set destroys grid data either, which is what earns it the same operation as the original three rather than one of its own.

Since issue #1798 (ADR-0081 §5), also required (alongside Self::SheetsWrite) for add-pivot-table — the first capability in the crate resolving two operations together rather than one. A pivot table is also a named, persistent, structural feature of a sheet, which is why it needs this operation too and not SheetsWrite alone.

Since issue #1832 (ADR-0082), also banded ranges (add-banding/update-banding/delete-banding) — alternating row/column colors applied to a range, the same “property of the sheet, not the sheet’s data” reasoning as unmerge-cells/clear-data-validation; removing one destroys no grid data.

Since issue #1833 (ADR-0084), also dimension groups (add-dimension-group/update-dimension-group/ delete-dimension-group) — the collapsible +/- outline over a row or column span, the same reasoning again; removing a group destroys no grid data either.

Since issue #1835 (ADR-0085), also update-sheet-properties — frozen rows/columns, tab color, right-to-left layout, and hidden gridlines, all per-sheet view state rather than grid data.

Since issue #1836 (ADR-0086), also update-workbook-properties — locale, time zone, automatic recalculation, and iterative calculation. The one capability in this variant with no sheet target at all, since it acts on the workbook itself; turning iterative calculation on changes what an unchanged circular-reference formula elsewhere evaluates to rather than touching any formula directly, the same shape of value effect ADR-0081 §2 already accepted here for named-range deletion.

Since issue #1838, also insert-range — the exact inverse of delete-range’s cell-range half, inserting empty cells into a sub-rectangle and shifting the existing cells in that column/row extent right or down. It joins this operation, not Self::SheetsDelete, because no cell value is discarded: every shifted cell keeps its content and the vacated cells become empty. The one asymmetry with delete-range: a cell pushed past the sheet’s current grid extent by the shift is silently dropped by the Sheets API, so this capability can lose data at the grid edge even though it destroys none within it.

Since issue #1837, also moving/resizing an existing chart or slicer (move-chart/move-slicer, updateEmbeddedObjectPosition) and setting or clearing a chart’s border colour (update-chart-border, updateEmbeddedObjectBorder) — the same operation as the rest of this chart/slicer set (add-chart/update-chart/delete-chart/ add-slicer/update-slicer/delete-slicer), since a move or a border change discards no data either.

Since issue #1839 (ADR-0083 §4), also required (alongside Self::SheetsWrite) for cut-paste unconditionally, and for copy-paste/paste-data when --paste-type is normal (formats and merges travel with the cell content) — plus required alone, no Self::SheetsWrite needed, for copy-paste/paste-data’s presentation-only format type, which writes nothing this crate treats as a cell value. cut-paste needs this operation whatever it pastes because the source is always cleared of its formats and merges too, the same “property of the sheet, not the sheet’s data” removal unmerge-cells/ clear-data-validation already make under this operation.

Deliberately not folded into Self::SheetsWrite, for the same reason that one is not folded into Self::Edit. Every existing allow: ["sheets-write"] rule was written when structural edits were impossible, so reusing it here would retroactively upgrade those rules into permission to restructure a workbook with no config change and no re-consent.

The same argument binds future work: row and sheet deletion must not later join this variant either, or granting it today would silently become consent to destroy data tomorrow. Nor may a permission change — see Self::SheetsProtection, carved out of this same deferred set for exactly that reason.

Since issue #1843 (ADR-0083 §§1, 5), also the second half of text-to-columns’ gate, alongside Self::SheetsWrite. Not because the split is a structural edit in itself, but because it was measured propagating the source cell’s formatting into spill cells that had none: a live split of a bold, pink column left every cell it wrote bold and pink. That is this operation’s own subject matter, so a sheets-write grant alone cannot confer it.

Since issue #1845 (ADR-0083 §§3, 5), also the second half of randomize-range’s gate, alongside Self::SheetsWrite. Not because a reorder is a structural edit in itself, but because it was measured carrying a row’s formatting, notes and data-validation rules with it, and rewriting the relative references of any formula moved along with it — a live probe reordering a bold, pink row with a note, a validation rule and a relative formula moved all four with the row. That is this operation’s own subject matter, so a sheets-write grant alone cannot confer it.

Since issue #1870, sort-range needs this operation too, alongside Self::SheetsWrite — the same live-verification finding as randomize-range: formatting, notes and data-validation rules travel with a reordered row, and an in-range relative formula rewrites to keep pointing at its own row. It shipped first (#1842) on SheetsWrite alone, before this was measured.

Since issue #1940, set-basic-filter --sort-by resolves this operation and Self::SheetsWrite — every other filter verb, and set-basic-filter without --sort-by, still resolves this one alone (ADR-0081 §1). A basic filter’s sort physically reorders the filtered range’s rows, the same permutation randomize-range performs, and the reorder outlives clear-basic-filter; so it takes randomize-range’s union rather than being treated as view state.

§

SheetsDelete

Destructively edit an existing Google Sheet via spreadsheets.batchUpdate (issue #1623, ADR-0077) — deleting a sheet, a row/column range, or an arbitrary cell range.

Deliberately not folded into Self::SheetsStructure, per the binding clause on that variant: every existing allow: ["sheets-structure"] rule was written when deletion was impossible, so reusing it here would retroactively upgrade those rules into permission to destroy data with no config change and no re-consent.

The same argument binds future work: no other operation should later join this variant without the same re-consent reasoning.

Since issue #1844 (ADR-0083 §2), also delete-duplicates — the first capability to join this variant since ADR-0077 defined it, and admitted under exactly the re-consent reasoning the clause above demands: an operator who granted sheets-delete consented to having cells removed and shifted up within a caller-named range by this tool, and delete-duplicates does just that. Content outside the range stays in place. It asks for nothing beyond that.

One thing about it is new, and is recorded here rather than buried in the verb: every other capability under this operation removes cells the caller named by address, whereas delete-duplicates removes rows the server selects from the data — by an equality rule that ignores letter case, formatting and formulas, and that reaches rows hidden by a filter. A sheets-delete grant used through this verb therefore deletes whatever that rule finds. ADR-0083 §2 accepts that as within the grant’s consent (rows removed from a range this tool was told to act on) and mitigates it where it belongs — in the verb, which states the rule in both the preview and the real run rather than implying the caller chose the rows.

§

SheetsProtection

Add, change or remove a protected range on an existing Google Sheet via spreadsheets.batchUpdate (issue #1643, ADR-0078).

Deliberately not folded into Self::SheetsStructure, and the reason is different in kind from every other split on this enum: a protected range is who may edit, not what the sheet contains. updateProtectedRange can widen the set of editors and deleteProtectedRange removes a guard someone deliberately placed — both are permission changes inside the document, closer in spirit to drive permissions than to any cell or structural write this tool makes. Folding it into sheets-structure would let a grant issued for “may reformat/validate/restructure this workbook” silently double as “may also change who can edit it” — a widening in kind, not merely in scope, which is why this earns its own operation rather than joining the set sheets-structure’s own doc comment just absorbed.

This binds future work too: nothing reachable under this operation may ever touch a file-level Drive permission (drive permissions is that surface, and stays the only one).

§

DocsWrite

Replace or append text in an existing Google Doc via the Docs API (issue #1615, ADR-0076 §2).

Folded into neither Self::Edit nor Self::SheetsWrite, and the argument runs in both directions. Every allow: ["edit"] rule was written when drive edit refused every Google-native document outright — which it still does. Every allow: ["sheets-write"] rule was written when Docs were unreachable through this tool, and that operation is lexically about cells, so making it govern prose would be a lie told by the config vocabulary itself.

This binds future work. A Docs deletion verb must not be folded into this variant either: a grant issued today for “may replace text” must not silently become consent to remove content tomorrow. When deletion is designed it needs its own operation, or explicit re-consent. Same rule ADR-0075 §1 records for sheets-structure.

Implementations§

Source§

impl DriveOperation

Source

pub const fn ever_requires_lease(self) -> bool

Whether an Allow verdict for this operation is ever backed by a Drive write lease requirement (issue #1917).

Read never mutates anything, and Create/Upload write into a new file — there is no existing content for a lease to protect, and neither engine (create.rs, upload.rs) ever gates on require_lease; the field appears on their LeasedWrite values only in test fixtures. Every other operation replaces or otherwise mutates a target’s existing content and does gate on it via decided_rule_requires_lease. This is consulted only by drive permissions check’s diagnostic, to keep it from reporting a lease requirement an operation could never actually be asked to satisfy — it does not itself change what any engine enforces.

Trait Implementations§

Source§

impl Clone for DriveOperation

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for DriveOperation

Source§

impl Debug for DriveOperation

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for DriveOperation

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for DriveOperation

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Matches the #[serde(rename_all = "kebab-case")] wire form — used by drive permissions show/check’s rendering.

Source§

impl Eq for DriveOperation

Source§

impl Hash for DriveOperation

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for DriveOperation

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for DriveOperation

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for DriveOperation

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ResetDiscriminant<T> for T
where T: Copy,

Source§

fn discriminant(&self) -> T

Value based on which equality for the reset will be determined.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToCompactString for T
where T: Display,

Source§

impl<T> ToLine for T
where T: Display,

Source§

fn to_line(&self) -> Line<'_>

Converts the value to a Line.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToSpan for T
where T: Display,

Source§

fn to_span(&self) -> Span<'_>

Converts the value to a Span.
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T> ToStringFallible for T
where T: Display,

Source§

fn try_to_string(&self) -> Result<String, TryReserveError>

ToString::to_string, but without panic on OOM.

Source§

impl<T> ToText for T
where T: Display,

Source§

fn to_text(&self) -> Text<'_>

Converts the value to a Text.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more