From bc0ecb8c8536eca460783e1f6c53d55898a78eb2 Mon Sep 17 00:00:00 2001 From: Jess Moore Date: Thu, 30 Jul 2026 22:01:59 +1000 Subject: [PATCH 1/7] preserve encryption state when overwriting content with writePod or writeExternalPod --- lib/src/solid/write_external_pod.dart | 26 +++++++++++++--- lib/src/solid/write_pod.dart | 44 ++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/lib/src/solid/write_external_pod.dart b/lib/src/solid/write_external_pod.dart index 4ad08166..cf9043e9 100644 --- a/lib/src/solid/write_external_pod.dart +++ b/lib/src/solid/write_external_pod.dart @@ -34,6 +34,7 @@ import 'dart:convert'; import 'package:flutter/material.dart' hide Key; import 'package:solidpod/src/solid/api/rest_api.dart'; +import 'package:solidpod/src/solid/check_encryption.dart' show isContentEncrypted; import 'package:solidpod/src/solid/common_func.dart'; import 'package:solidpod/src/solid/constants/common.dart'; import 'package:solidpod/src/solid/utils/exceptions.dart'; @@ -44,7 +45,17 @@ import 'package:solidpod/src/solid/utils/misc.dart'; /// Write file [fileUrl] with content [fileContent] to an external PODs in the /// data directory (within potential subdirectories encoded in [fileUrl]). -/// The content will be encrypted if the original content is true. +/// +/// [encrypted] defaults to `null`, meaning "not specified by the caller": when +/// overwriting an existing file, the file's *current* at-rest state on the +/// server is mirrored (plaintext stays plaintext, ciphertext stays +/// ciphertext) rather than always re-encrypting just because a shared +/// individual key happens to be on record. This matters for a resource the +/// owner decrypted in place for Public/Authenticated User sharing (see +/// `decryptFileInPlace` in solidpod) — without this, a recipient with write +/// access editing the file would silently re-encrypt it and break that +/// sharing grant. Pass `true`/`false` explicitly to force a specific +/// encryption state regardless of what's currently on the server. /// /// The encryption boilerplate shared with [writePod] is factored out into /// [getEncTTLStrWithRandomIV], and the "own POD vs external POD" routing is @@ -57,7 +68,7 @@ Future writeExternalPod( String fileUrl, String fileContent, String fileOwnerWebId, { - bool encrypted = true, + bool? encrypted, bool overwrite = true, String? inheritKeyFrom, }) async { @@ -89,9 +100,16 @@ Future writeExternalPod( case ResourceStatus.exist: final remoteFileContent = utf8.decode(await getResource(fileUrl)); + // When the caller didn't specify [encrypted], mirror whatever is + // actually on the server right now instead of assuming a shared key + // on record means the file should be (re-)encrypted — the owner may + // have decrypted it in place for Public/Authenticated User sharing. + final wantEncrypted = encrypted ?? + isContentEncrypted(fileUrl: fileUrl, content: remoteFileContent); + final key = await KeyManager.getSharedIndividualKey(fileUrl); - if (key != null) { + if (wantEncrypted && key != null) { // Get file path // final filePath = // fileUrl.replaceAll(fileOwnerWebId.replaceAll(profCard, ''), ''); @@ -108,7 +126,7 @@ Future writeExternalPod( 'but the extension of provided filename "$fileUrl" is not ".ttl"', ); } - } else if (hasInheritedKey(remoteFileContent, fileUrl)) { + } else if (wantEncrypted && hasInheritedKey(remoteFileContent, fileUrl)) { // Get file path // final filePath = // fileUrl.replaceAll(fileOwnerWebId.replaceAll(profCard, ''), ''); diff --git a/lib/src/solid/write_pod.dart b/lib/src/solid/write_pod.dart index e2efbd88..ebeaa604 100644 --- a/lib/src/solid/write_pod.dart +++ b/lib/src/solid/write_pod.dart @@ -28,12 +28,16 @@ library; +import 'dart:convert' show utf8; + import 'package:flutter/foundation.dart' show debugPrint; import 'package:encrypter_plus/encrypter_plus.dart' show Key; import 'package:mime/mime.dart' as mime; import 'package:solidpod/src/solid/api/rest_api.dart'; +import 'package:solidpod/src/solid/check_encryption.dart' + show isContentEncrypted; import 'package:solidpod/src/solid/constants/common.dart'; import 'package:solidpod/src/solid/constants/path_type.dart'; import 'package:solidpod/src/solid/utils/exceptions.dart'; @@ -58,7 +62,18 @@ import 'package:solidpod/src/solid/write_external_pod.dart' /// Arguments: /// - [filePath]: The path (relative to appname/data/) of the file to write /// - [fileContent]: The content to write to the file -/// - [encrypted]: Whether to encrypt the file content (default: true) +/// - [encrypted]: Whether to encrypt the file content. Defaults to `null`, +/// meaning "not specified by the caller": for a new file (or when +/// [overwrite] is false) this behaves as `true`; when [overwrite] is true +/// and the file already exists, the file's *current* at-rest state on the +/// server is mirrored instead (plaintext stays plaintext, ciphertext stays +/// ciphertext). This matters for a resource that was decrypted in place +/// for Public/Authenticated User sharing (see `decryptFileInPlace`) — +/// without this, an unrelated edit would silently re-encrypt it and break +/// that sharing grant, since a class-based ACL grant has no key to +/// decrypt with. Pass `true`/`false` explicitly to override this and +/// force a specific encryption state regardless of what's currently on +/// the server. /// - [createAcl]: Whether to create a separate acl for the resource (default: true) /// - [overwrite]: Whether to overwrite the content of an existing file (default: false) /// - [pathType]: Optional type of relative path (for both [filePath] and [inheritKeyFrom]) @@ -80,7 +95,7 @@ import 'package:solidpod/src/solid/write_external_pod.dart' Future writePod( String filePath, String fileContent, { - bool encrypted = true, + bool? encrypted, bool createAcl = true, bool overwrite = false, PathType pathType = PathType.relativeToData, @@ -133,6 +148,27 @@ Future writePod( ); } + final status = await checkResourceStatus(fileUrl); + + // Resolve the effective encryption flag. When the caller didn't specify + // [encrypted] and this is an overwrite of an existing file, mirror the + // file's current at-rest state instead of assuming `true` — otherwise an + // unrelated edit would silently re-encrypt a file that was deliberately + // decrypted in place for Public/Authenticated User sharing (see + // `decryptFileInPlace`), stranding a resource whose ACL still promises + // open access but whose bytes no longer are. + + var resolvedEncrypted = encrypted ?? true; + if (encrypted == null && + inheritKeyFrom == null && + overwrite && + status == ResourceStatus.exist) { + final currentContent = utf8.decode(await getResource(fileUrl)); + // Determine current encryption state + resolvedEncrypted = + isContentEncrypted(fileUrl: fileUrl, content: currentContent); + } + Key? encKey; String? inheritKeyUrl; if (inheritKeyFrom != null) { @@ -143,7 +179,7 @@ Future writePod( ); } - if (encrypted || inheritKeyFrom != null) { + if (resolvedEncrypted || inheritKeyFrom != null) { if (!fileUrl.endsWith('.ttl')) { throw Exception( 'Encrypted text file should be in turtle format, ' @@ -154,7 +190,7 @@ Future writePod( encKey = await configureEncKey(fileUrl, inheritKeyUrl: inheritKeyUrl); } - switch (await checkResourceStatus(fileUrl)) { + switch (status) { case ResourceStatus.exist: if (overwrite) { debugPrint('NOTE: Overwriting existing file "$filePath"'); From ebaf59a0b940e0191cdfc7823ef86e2dbfcb9d0f Mon Sep 17 00:00:00 2001 From: Jess Moore Date: Thu, 30 Jul 2026 22:02:13 +1000 Subject: [PATCH 2/7] update changelog and bump minor version --- CHANGELOG.md | 7 ++++--- pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f69e097..98062e24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,9 @@ Visit the package at [pub.dev](https://pub.dev/packages/solidpod). ## 1.0 ++ Preserve encryption state on overwrite in writePod/writeExternalPod [1.0.14 20260730 jesscmoore] + Add load test to the example app [1.0.13 20260702 tonypioneer] -+ Migrate TEMPALTE to solidui [1.0.12 20260629 tonypioneer] ++ Migrate TEMPLATE to solidui [1.0.12 20260629 tonypioneer] + Support profile editing [1.0.11 20260626 tonypioneer] + Bug fix template for dart run [1.0.10 20260622 tonypioneer] + Add app template for a 'create' experience [1.0.9 20260619 tonypioneer] @@ -32,8 +33,8 @@ Visit the package at [pub.dev](https://pub.dev/packages/solidpod). + Check missing resources [0.12.9 20260520 tonypioneer] + Support checking webID [0.12.8 20260520 tonypioneer] + Update Try Another WebID workflow [0.12.7 20260520 tonypioneer] -+ Bug fix to ttl rdf for special chars #628 [0.12.6 20260518 tonypioneer] -+ Upgrade solidauth and fix key file saving edge cases [0.12.5 20260427 jesscmoore] ++ Bug fix to ttl RDF for special chars #628 [0.12.6 20260518 tonypioneer] ++ Upgrade solid_auth and fix key file saving edge cases [0.12.5 20260427 jesscmoore] + Support user profile. [0.12.4 20260421 tonypioneer] + Key map + paths updates. Update file_picker. [0.12.3 20260420 jesscmoore] + Add silentLogout() [0.12.2 20260325 tonypioneer] diff --git a/pubspec.yaml b/pubspec.yaml index cbdcb728..9f662d6a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: solidpod description: Support access to private data from PODs on Solid servers. -version: 1.0.13 +version: 1.0.14 homepage: https://github.com/anusii/solidpod environment: From c0ed5e911083639e1dfd5a345421f2ab59a61980 Mon Sep 17 00:00:00 2001 From: Jess Moore Date: Mon, 3 Aug 2026 13:27:59 +1000 Subject: [PATCH 3/7] dart format --- lib/src/solid/write_external_pod.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/solid/write_external_pod.dart b/lib/src/solid/write_external_pod.dart index cf9043e9..74970dd6 100644 --- a/lib/src/solid/write_external_pod.dart +++ b/lib/src/solid/write_external_pod.dart @@ -34,7 +34,8 @@ import 'dart:convert'; import 'package:flutter/material.dart' hide Key; import 'package:solidpod/src/solid/api/rest_api.dart'; -import 'package:solidpod/src/solid/check_encryption.dart' show isContentEncrypted; +import 'package:solidpod/src/solid/check_encryption.dart' + show isContentEncrypted; import 'package:solidpod/src/solid/common_func.dart'; import 'package:solidpod/src/solid/constants/common.dart'; import 'package:solidpod/src/solid/utils/exceptions.dart'; From 2e27bf90d64dd424c8ceb60c16555e57fec197f4 Mon Sep 17 00:00:00 2001 From: Jess Moore Date: Mon, 3 Aug 2026 13:29:07 +1000 Subject: [PATCH 4/7] markdownlint fix --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98062e24..581a83c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ Visit the package at [pub.dev](https://pub.dev/packages/solidpod). ## 1.0 -+ Preserve encryption state on overwrite in writePod/writeExternalPod [1.0.14 20260730 jesscmoore] ++ Preserve encryption state on overwrite [1.0.14 20260730 jesscmoore] + Add load test to the example app [1.0.13 20260702 tonypioneer] + Migrate TEMPLATE to solidui [1.0.12 20260629 tonypioneer] + Support profile editing [1.0.11 20260626 tonypioneer] From 52f0cbac4556cca408d3b113dede5ce50b41384f Mon Sep 17 00:00:00 2001 From: Jess Moore Date: Tue, 11 Aug 2026 15:37:38 +1000 Subject: [PATCH 5/7] adds catch for call of encrypted true and public shared --- lib/solidpod.dart | 1 + lib/src/solid/utils/exceptions.dart | 22 ++++++++++++++ lib/src/solid/utils/permission.dart | 35 ++++++++++++++++++++++ lib/src/solid/write_external_pod.dart | 40 +++++++++++++++++++++++-- lib/src/solid/write_pod.dart | 43 ++++++++++++++++++++++++--- 5 files changed, 135 insertions(+), 6 deletions(-) diff --git a/lib/solidpod.dart b/lib/solidpod.dart index 3e8be640..0817fd48 100644 --- a/lib/solidpod.dart +++ b/lib/solidpod.dart @@ -100,6 +100,7 @@ export 'src/solid/utils/exceptions.dart' CssEmailAlreadyRegisteredException, CssWrongCredentialsException, NotLoggedInException, + PublicShareEncryptionConflictException, RecipientNotReadyException, ResourceNotDecryptableException, ResourceNotExistException, diff --git a/lib/src/solid/utils/exceptions.dart b/lib/src/solid/utils/exceptions.dart index 8bc845a2..54d0e4c1 100644 --- a/lib/src/solid/utils/exceptions.dart +++ b/lib/src/solid/utils/exceptions.dart @@ -163,3 +163,25 @@ class CssEmailAlreadyRegisteredException implements Exception { @override String toString() => 'CssEmailAlreadyRegisteredException: $message'; } + +/// Thrown by [writePod] when a write would encrypt a resource whose ACL +/// still grants the Public or Authenticated User agent class access — a +/// grant that only works while the resource stays plaintext (those agent +/// classes cannot be issued an individual decryption key). This usually +/// means the resource was deliberately decrypted in place for sharing (see +/// `decryptFileInPlace`) and the caller passed an explicit `encrypted: true` +/// (or `inheritKeyFrom`) without meaning to undo that sharing grant. +/// +/// To fix: call `revokePermission` to remove the Public/Authenticated grant +/// first (it re-encrypts the resource as part of revocation), or omit +/// `encrypted` / pass `encrypted: false` to preserve the current plaintext +/// state. + +class PublicShareEncryptionConflictException implements Exception { + final String message; + + PublicShareEncryptionConflictException(this.message); + + @override + String toString() => 'PublicShareEncryptionConflictException: $message'; +} diff --git a/lib/src/solid/utils/permission.dart b/lib/src/solid/utils/permission.dart index f79c12ee..f027a19d 100644 --- a/lib/src/solid/utils/permission.dart +++ b/lib/src/solid/utils/permission.dart @@ -31,6 +31,8 @@ import 'dart:convert'; import 'package:rdflib/rdflib.dart' show URIRef, Namespace; import 'package:solidpod/src/solid/api/rest_api.dart'; +import 'package:solidpod/src/solid/constants/common.dart' + show ResourceStatus, authAgent, pubAgent; import 'package:solidpod/src/solid/constants/web_acl.dart'; import 'package:solidpod/src/solid/utils/authdata_manager.dart'; import 'package:solidpod/src/solid/utils/misc.dart' show getResAclFile; @@ -184,6 +186,39 @@ Future> readAcl( return parseACL(aclContent); } +/// Whether [resourceUrl]'s ACL currently grants read access to the Public +/// or Authenticated User agent class. +/// +/// Those agent classes cannot be issued an individual decryption key (see +/// `decryptFileInPlace`), so a `true` result means the resource's bytes are +/// expected to stay plaintext at rest for as long as the grant exists — +/// [writePod] uses this to avoid silently re-encrypting a resource that a +/// prior `grantPermission` call deliberately decrypted for sharing. +/// +/// Returns `false` when the resource has no dedicated ACL file yet (nothing +/// to check). + +Future hasPublicOrAuthUserGrant( + String resourceUrl, { + bool isFile = true, +}) async { + final aclFileUrl = getResAclFile(resourceUrl, isFile); + if (await checkResourceStatus(aclFileUrl) != ResourceStatus.exist) { + return false; + } + + final aclMap = await readAcl(resourceUrl, isFile); + for (final predicates in aclMap.values) { + final agentClasses = (predicates as Map)['agentClass']; + if (agentClasses is List && + (agentClasses.contains(pubAgent) || + agentClasses.contains(authAgent))) { + return true; + } + } + return false; +} + /// Retrieves the list of WebIDs defined in a ttl file as a vcard:Group /// /// Returns a Future that completes with a List containing the list of WebIDs. diff --git a/lib/src/solid/write_external_pod.dart b/lib/src/solid/write_external_pod.dart index 74970dd6..b4e222df 100644 --- a/lib/src/solid/write_external_pod.dart +++ b/lib/src/solid/write_external_pod.dart @@ -43,6 +43,8 @@ import 'package:solidpod/src/solid/utils/get_url_helper.dart'; import 'package:solidpod/src/solid/utils/key_inheritance.dart'; import 'package:solidpod/src/solid/utils/key_manager.dart' show KeyManager; import 'package:solidpod/src/solid/utils/misc.dart'; +import 'package:solidpod/src/solid/utils/permission.dart' + show hasPublicOrAuthUserGrant; /// Write file [fileUrl] with content [fileContent] to an external PODs in the /// data directory (within potential subdirectories encoded in [fileUrl]). @@ -55,8 +57,19 @@ import 'package:solidpod/src/solid/utils/misc.dart'; /// owner decrypted in place for Public/Authenticated User sharing (see /// `decryptFileInPlace` in solidpod) — without this, a recipient with write /// access editing the file would silently re-encrypt it and break that -/// sharing grant. Pass `true`/`false` explicitly to force a specific -/// encryption state regardless of what's currently on the server. +/// sharing grant. +/// +/// Passing `true`/`false` explicitly overrides the mirroring above and +/// forces that encryption state. Leave [encrypted] unset whenever you're +/// only touching content and not intentionally changing whether it's +/// encrypted. If forcing encryption would break an active +/// Public/Authenticated sharing grant on the resource (i.e. its ACL still +/// grants that class access — readable only when the caller happens to hold +/// acl:Control on it, which a recipient with mere Read/Write access +/// typically does not), the call throws +/// [PublicShareEncryptionConflictException] instead of silently stranding +/// the grant. The resource owner should call `revokePermission` to remove +/// the grant first (it handles re-encrypting the resource itself). /// /// The encryption boilerplate shared with [writePod] is factored out into /// [getEncTTLStrWithRandomIV], and the "own POD vs external POD" routing is @@ -110,6 +123,29 @@ Future writeExternalPod( final key = await KeyManager.getSharedIndividualKey(fileUrl); + // Refuse to write ciphertext over a resource whose ACL still grants + // the Public or Authenticated User agent class access — that grant + // only works while the resource stays plaintext. This only fires when + // [wantEncrypted] was forced by an explicit `encrypted: true`; the + // auto-detect path above already mirrors the resource's actual + // current state, so a resource that's genuinely still plaintext never + // trips it. (When the caller lacks acl:Control on the resource, the + // ACL read fails closed to "no grant found" rather than blocking the + // write — see [hasPublicOrAuthUserGrant].) + + if (encrypted == true && + (key != null || hasInheritedKey(remoteFileContent, fileUrl)) && + await hasPublicOrAuthUserGrant(fileUrl)) { + throw PublicShareEncryptionConflictException( + 'Refusing to write encrypted content to "$fileUrl": its ACL ' + 'grants Public/Authenticated User access, which requires the ' + 'resource to stay plaintext. Ask the resource owner to call ' + 'revokePermission() to remove that grant (it re-encrypts the ' + 'resource as part of revocation), or omit "encrypted" (or pass ' + 'encrypted: false) to preserve its current plaintext state.', + ); + } + if (wantEncrypted && key != null) { // Get file path // final filePath = diff --git a/lib/src/solid/write_pod.dart b/lib/src/solid/write_pod.dart index ebeaa604..95b899ed 100644 --- a/lib/src/solid/write_pod.dart +++ b/lib/src/solid/write_pod.dart @@ -44,7 +44,8 @@ import 'package:solidpod/src/solid/utils/exceptions.dart'; import 'package:solidpod/src/solid/utils/io_helper.dart'; import 'package:solidpod/src/solid/utils/key_inheritance.dart'; import 'package:solidpod/src/solid/utils/misc.dart'; -import 'package:solidpod/src/solid/utils/permission.dart' show genAclTurtle; +import 'package:solidpod/src/solid/utils/permission.dart' + show genAclTurtle, hasPublicOrAuthUserGrant; import 'package:solidpod/src/solid/write_external_pod.dart' show writeExternalPod; @@ -71,9 +72,19 @@ import 'package:solidpod/src/solid/write_external_pod.dart' /// for Public/Authenticated User sharing (see `decryptFileInPlace`) — /// without this, an unrelated edit would silently re-encrypt it and break /// that sharing grant, since a class-based ACL grant has no key to -/// decrypt with. Pass `true`/`false` explicitly to override this and -/// force a specific encryption state regardless of what's currently on -/// the server. +/// decrypt with. +/// +/// Passing `true`/`false` explicitly (or setting [inheritKeyFrom]) +/// overrides the mirroring above and forces that encryption state, +/// because some callers genuinely need to — e.g. toggling a resource's +/// privacy, or restoring a backed-up encryption state. Leave [encrypted] +/// unset whenever you're only touching content and not intentionally +/// changing whether it's encrypted. If forcing encryption would break an +/// active Public/Authenticated sharing grant (i.e. the resource's ACL +/// still grants that class access), the call throws +/// [PublicShareEncryptionConflictException] instead of silently +/// stranding the grant — call `revokePermission` to remove the grant +/// first (it handles re-encrypting the resource itself). /// - [createAcl]: Whether to create a separate acl for the resource (default: true) /// - [overwrite]: Whether to overwrite the content of an existing file (default: false) /// - [pathType]: Optional type of relative path (for both [filePath] and [inheritKeyFrom]) @@ -169,6 +180,30 @@ Future writePod( isContentEncrypted(fileUrl: fileUrl, content: currentContent); } + // Refuse to write ciphertext over a resource whose ACL still grants the + // Public or Authenticated User agent class access. That grant only works + // while the resource stays plaintext (those agent classes cannot be + // issued an individual decryption key), so a resource in this state was + // deliberately decrypted in place for sharing (see `decryptFileInPlace`). + // This only fires when [resolvedEncrypted] was forced to `true` by an + // explicit `encrypted: true` or by [inheritKeyFrom] — the auto-detect + // path above already mirrors the resource's actual current state, so it + // never trips this for a resource that's genuinely still plaintext. + + if (overwrite && + status == ResourceStatus.exist && + (resolvedEncrypted || inheritKeyFrom != null) && + await hasPublicOrAuthUserGrant(fileUrl)) { + throw PublicShareEncryptionConflictException( + 'Refusing to write encrypted content to "$filePath": its ACL grants ' + 'Public/Authenticated User access, which requires the resource to ' + 'stay plaintext. Call revokePermission() to remove that grant ' + '(it re-encrypts the resource as part of revocation), or omit ' + '"encrypted" (or pass encrypted: false) to preserve its current ' + 'plaintext state.', + ); + } + Key? encKey; String? inheritKeyUrl; if (inheritKeyFrom != null) { From 2f8620f156b85ca6215caf60654173dd4e9ac349 Mon Sep 17 00:00:00 2001 From: Jess Moore Date: Tue, 11 Aug 2026 15:41:02 +1000 Subject: [PATCH 6/7] linted --- lib/src/solid/utils/permission.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/src/solid/utils/permission.dart b/lib/src/solid/utils/permission.dart index f027a19d..af522c8a 100644 --- a/lib/src/solid/utils/permission.dart +++ b/lib/src/solid/utils/permission.dart @@ -211,8 +211,7 @@ Future hasPublicOrAuthUserGrant( for (final predicates in aclMap.values) { final agentClasses = (predicates as Map)['agentClass']; if (agentClasses is List && - (agentClasses.contains(pubAgent) || - agentClasses.contains(authAgent))) { + (agentClasses.contains(pubAgent) || agentClasses.contains(authAgent))) { return true; } } From c6e418c0ac74fea3ce0fcbdd9f95351e9bde23ed Mon Sep 17 00:00:00 2001 From: Jess Moore Date: Tue, 11 Aug 2026 15:47:58 +1000 Subject: [PATCH 7/7] remove deprecated --exclude-file in link checker --- .github/workflows/ci.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 86cc5434..0071c02b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,7 +16,6 @@ env: FLUTTER_VERSION: '3.44.2' jobs: - analyze: runs-on: ubuntu-latest if: github.event.repository.private == false @@ -103,8 +102,7 @@ jobs: id: lychee uses: lycheeverse/lychee-action@v2 with: # Don't fail for now but then create an issue - useful? - args: - --exclude-file .lycheeignore + args: --exclude-path .lycheeignore --no-progress '*.md' './**/*.dart'