Skip to content

fix(android): bind retained documents to accounts - #447

Open
veryCrunchy wants to merge 27 commits into
feature/account-credential-slotsfrom
fix/document-grant-incarnation
Open

fix(android): bind retained documents to accounts#447
veryCrunchy wants to merge 27 commits into
feature/account-credential-slotsfrom
fix/document-grant-incarnation

Conversation

@veryCrunchy

Copy link
Copy Markdown
Member

Summary

  • Give retained DocumentsProvider grants an account incarnation so removing and re-adding an account invalidates old URIs.
  • Resolve documents through their owning account instead of whichever account is active.
  • Journal grant retirement so interrupted removal can roll forward or back safely.
  • Hold the account-operation lease for retained reads and searches, and avoid reentrant provider-mutation locking.

Validation

  • Full repository and architecture checks passed.
  • Build host: focused 8-class Android provider/removal suite passed.
  • Build host: :androidApp:assembleDebug passed.
  • Exact validated tree: c9a314df55e510df3f1478288955c06c5223e3aa.

@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 5, 2026 15:38 Destroyed
@obiente-cloud

obiente-cloud Bot commented Sep 5, 2026

Copy link
Copy Markdown

Obiente preview

NC Native · fd3016e99c0f · Ready

Open preview

View in Obiente

Obiente updates this comment as the preview changes.

@veryCrunchy
veryCrunchy marked this pull request as ready for review September 5, 2026 15:39
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 5, 2026 15:39 Destroyed
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-06T11:27:08.527049Z 7f70d10 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f97f74994f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 5, 2026 22:30 Destroyed
@veryCrunchy
veryCrunchy force-pushed the feature/account-credential-slots branch from a80069c to 722eb39 Compare September 5, 2026 22:42
@veryCrunchy
veryCrunchy force-pushed the fix/document-grant-incarnation branch from 00333f6 to 8266aab Compare September 5, 2026 22:53
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 5, 2026 22:53 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8266aabbc2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 5, 2026 23:19 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e6b7830d96

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 5, 2026 23:52 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 888fbf8e00

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@veryCrunchy
veryCrunchy force-pushed the feature/account-credential-slots branch 2 times, most recently from dfdae5f to 871e131 Compare September 6, 2026 04:42
@veryCrunchy
veryCrunchy force-pushed the fix/document-grant-incarnation branch from 888fbf8 to 74b43bf Compare September 6, 2026 04:48
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 6, 2026 04:48 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 74b43bf122

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@veryCrunchy
veryCrunchy force-pushed the feature/account-credential-slots branch from a10ff29 to 5bd8032 Compare September 6, 2026 05:05
@veryCrunchy
veryCrunchy force-pushed the fix/document-grant-incarnation branch from 74b43bf to b1fc365 Compare September 6, 2026 06:00
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 6, 2026 06:00 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b1fc365e26

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 6, 2026 06:20 Destroyed
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 6, 2026 06:32 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 904fa387ba

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

accountLease: AndroidAccountOperationLease,
handler: Handler,
): ParcelFileDescriptor = try {
ParcelFileDescriptor.open(content, ParcelFileDescriptor.MODE_READ_ONLY, handler) { accountLease.close() }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve read fencing across provider process death

When a SAF client keeps this cached/offline descriptor open and the provider process is killed before the client closes it, the client retains its duplicated raw file descriptor but accountLease and the lifetime guard disappear with the provider process. After restart, account removal observes no reader and can complete and unlink the cache, while the client continues reading the already-open inode. Use a revocable proxy rather than handing out raw cache descriptors, or otherwise make the removal fence process-restorable.

AGENTS.md reference: AGENTS.md:L457-L461

Useful? React with 👍 / 👎.

Comment on lines 210 to +214
rollbackUnavailableAndroidAccountRemoval(
active = target.wasActive, recovered = recovered, persistRecovered = { state -> persistState(state) },
clearCleanup = { accountRemovalCleanupJournal.clear(accountId.storageKey) },
clearCleanup = {
rollbackAndroidAccountRemoval(appContext, requireNotNull(documentRetirement))
accountRemovalCleanupJournal.clear(accountId.storageKey)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep the tombstone after a committed unavailable removal

When the active account's credential slot is unavailable and clearSession(recovered, pendingCleanup, unavailableSession) successfully commits the registry removal but its subsequent roots notification throws, this rollback path does not restore the registry because rollbackUnavailableAndroidAccountRemoval(active = true) skips persistRecovered; it nevertheless restores the old document incarnation and clears the cleanup marker. Re-adding the now-absent account can therefore reuse that active incarnation and reactivate old URI grants. The fresh path here is the post-commit notifyDocumentRootsChanged() failure in clearSession, rather than concurrent reconciliation; make that notification best-effort or retain the tombstone once ownership removal committed.

AGENTS.md reference: AGENTS.md:L397-L398

Useful? React with 👍 / 👎.

@veryCrunchy
veryCrunchy force-pushed the fix/document-grant-incarnation branch from 904fa38 to 8f53cf8 Compare September 6, 2026 07:07
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 6, 2026 07:07 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8f53cf8e18

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +846 to +848
return withAndroidDocumentMutation(
session = resolved.session,
loadCurrentSession = { services.loadSession(resolved.session.accountId) },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fence inactive-account writes by canonical identity

When a document mutation targets an inactive account while saveSession() reauthenticates that same account using a canonically equivalent server spelling, this path acquires the operation guard under the old raw NextcloudDocumentIds.accountKey. The credential transition guards only the previously active account and the replacement session's new raw key (AndroidAccountCredentialController.kt:434-438), so it can persist the replacement concurrently while create, rename, move, or delete continues with the captured old credentials. Key the mutation fence by accountId.storageKey, or also fence the stored session's prior key, so credential replacement cannot leave an in-flight write operating on stale identity state.

AGENTS.md reference: AGENTS.md:L373-L376

Useful? React with 👍 / 👎.

@veryCrunchy
veryCrunchy force-pushed the fix/document-grant-incarnation branch from 99f6848 to 7f70d10 Compare September 6, 2026 11:17
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #447 / NC Native September 6, 2026 11:17 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7f70d10a98

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +231 to +234
} catch (_: IllegalArgumentException) {
quarantineMalformedPendingRetirement(accountIdentity)
null
} catch (_: ClassCastException) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Catch invalid UTF-8 while quarantining reset journals

When a retirement journal contains canonical Base64 that decodes to invalid UTF-8 (for example, _w in a present field), decodeRetirementField() throws CharacterCodingException, but this recovery catches only IllegalArgumentException and ClassCastException. The exception therefore escapes prepareForCredentialReset() before clearCredentials() runs, leaving the explicit credential reset unusable. The fresh evidence beyond the earlier malformed-journal report is this new quarantine handler's exception whitelist, which still excludes the UTF-8 decoder failure; catch that failure or normalize it into the handled malformed-input type.

AGENTS.md reference: AGENTS.md:L325-L326

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant