6 Commits
Author SHA1 Message Date
Puranjay Savar Mattas 7c083b0ba5 fix: silence unused withLock result warning in OutlineImageProvider
lock.withLock { inFlight.remove(url) } inside the defer returned
Set.remove's String? result unused - withLock mirrors its closure's
return type, so an unused Set.remove leaked through as an unused
withLock result. Explicitly discard it inside the closure instead.
2026-08-21 04:40:33 +01:00
Puranjay Savar Mattas d0b6b35bda fix: lower project file format from objectVersion 110 to 77
Xcode Cloud (running a stable, non-beta Xcode) rejected the project
outright: "cannot be opened because it is in a future Xcode project
file format (110)". 110 is whatever the local beta Xcode (this whole
project has been developed against Xcode 27 beta) bumps the format to
on save - not something the project actually needs.

The project itself already had the answer: preferredProjectObjectVersion
= 77 was already present, Xcode's own note that 77 is the actual
minimum format required (it's what introduced fileSystemSynchronizedGroups,
which this project uses - the mechanism that's been letting new source
files just get picked up without explicit PBXFileReference entries all
session). Set objectVersion to match.

Opening/saving this project again in the local beta Xcode will very
likely bump objectVersion back to 110 silently - worth checking this
value before any future push if that happens.
2026-08-21 04:35:43 +01:00
Puranjay Savar Mattas 289e3062a1 chore: bump build number to 3 (0.1.0 build 3)
CURRENT_PROJECT_VERSION 2 -> 3 for the Outpost app target only
(Debug + Release), test targets left alone. OutpostVersion.swift's
buildNumber fallback and doc-comment updated to match.
2026-08-21 03:41:03 +01:00
Puranjay Savar Mattas 71070daf86 chore: bump build number to 2 (0.1.0 build 2)
CURRENT_PROJECT_VERSION 1 -> 2 for the Outpost app target (Debug +
Release only, test targets left alone, same scope as the
MARKETING_VERSION bump). OutpostVersion.swift's buildNumber fallback
and doc-comment example updated to match.
2026-08-21 02:55:19 +01:00
Puranjay Savar Mattas f1cc8607b0 fix: lower macOS deployment target from 27.0 to 14.0
MACOSX_DEPLOYMENT_TARGET was 27.0 across all 6 build configs (app +
both test targets) - an artifact of Xcode defaulting it to match the
beta SDK this is developed against, not an actual code requirement.
At 27.0 the app would only install for people running a macOS beta
that doesn't even exist for the general public yet.

14.0 is the real floor, already documented as the target in
CLAUDE.md ("macOS 14+ minimum, needed for mature AttributedString/
TextKit 2 APIs") and required independently by @Observable/SwiftData,
which are used throughout (SessionStore, StarStore, TipJarStore,
OfflineCacheStore, APIFailureCenter, etc.). Everything else added
this session - StoreKit 2, ImageRenderer, requestReview, CryptoKit -
is available well before 14, so nothing pushes the floor higher.

README's "macOS 27+" end-user requirement corrected to 14+ to match
(the "Xcode 27+" line just above it is a separate, still-accurate
build-from-source requirement, left alone).

Not compiler-verified against the 14.0 SDK - this project has never
actually been built with this deployment target before (always 27.0
during this session's development), so a real Xcode build now may
surface "only available in macOS 15+/26+" errors on any API used
without realizing it needed newer than 14. Needs an actual build
before submission, not just a lower number in the project file.
2026-08-21 02:53:26 +01:00
Puranjay Savar Mattas 48377668b0 Merge pull request 'v0.1.0 stability, security, and App Store readiness' (#14) from chore/v0.1.0-stability-audit into main
Reviewed-on: #14
2026-08-21 02:02:23 +01:00
4 changed files with 13 additions and 13 deletions
+9 -9
View File
@@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 110; objectVersion = 77;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@@ -402,7 +402,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = CW6GQT9SK5; DEVELOPMENT_TEAM = CW6GQT9SK5;
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@@ -424,7 +424,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 27.0; IPHONEOS_DEPLOYMENT_TARGET = 27.0;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 27.0; MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 0.1.0; MARKETING_VERSION = 0.1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostApp; PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostApp;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -454,7 +454,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = CW6GQT9SK5; DEVELOPMENT_TEAM = CW6GQT9SK5;
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@@ -476,7 +476,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 27.0; IPHONEOS_DEPLOYMENT_TARGET = 27.0;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 27.0; MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 0.1.0; MARKETING_VERSION = 0.1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostApp; PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostApp;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -505,7 +505,7 @@
DEVELOPMENT_TEAM = CW6GQT9SK5; DEVELOPMENT_TEAM = CW6GQT9SK5;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 27.0; IPHONEOS_DEPLOYMENT_TARGET = 27.0;
MACOSX_DEPLOYMENT_TARGET = 27.0; MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostTests; PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -531,7 +531,7 @@
DEVELOPMENT_TEAM = CW6GQT9SK5; DEVELOPMENT_TEAM = CW6GQT9SK5;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 27.0; IPHONEOS_DEPLOYMENT_TARGET = 27.0;
MACOSX_DEPLOYMENT_TARGET = 27.0; MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostTests; PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -556,7 +556,7 @@
DEVELOPMENT_TEAM = CW6GQT9SK5; DEVELOPMENT_TEAM = CW6GQT9SK5;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 27.0; IPHONEOS_DEPLOYMENT_TARGET = 27.0;
MACOSX_DEPLOYMENT_TARGET = 27.0; MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostUITests; PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostUITests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -581,7 +581,7 @@
DEVELOPMENT_TEAM = CW6GQT9SK5; DEVELOPMENT_TEAM = CW6GQT9SK5;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 27.0; IPHONEOS_DEPLOYMENT_TARGET = 27.0;
MACOSX_DEPLOYMENT_TARGET = 27.0; MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostUITests; PRODUCT_BUNDLE_IDENTIFIER = com.psmattas.OutpostUITests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
+1 -1
View File
@@ -61,7 +61,7 @@ final class OutlineImageProvider: EmbeddedImageProvider, @unchecked Sendable {
guard !alreadyLoading else { return } guard !alreadyLoading else { return }
Task { Task {
defer { lock.withLock { inFlight.remove(url) } } defer { lock.withLock { _ = inFlight.remove(url) } }
do { do {
let data: Data let data: Data
if url.hasPrefix("http://") || url.hasPrefix("https://"), let externalURL = URL(string: url) { if url.hasPrefix("http://") || url.hasPrefix("https://"), let externalURL = URL(string: url) {
+2 -2
View File
@@ -17,7 +17,7 @@ enum OutpostVersion {
} }
static var buildNumber: String { static var buildNumber: String {
Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? "1" Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? "3"
} }
/// e.g. `"0.1.0"` for compact display (sidebar footer). /// e.g. `"0.1.0"` for compact display (sidebar footer).
@@ -26,7 +26,7 @@ enum OutpostVersion {
return "\(shortVersion)\(stageSuffix)" return "\(shortVersion)\(stageSuffix)"
} }
/// e.g. `"Version 0.1.0 (1)"` for the About page. /// e.g. `"Version 0.1.0 (3)"` for the About page.
static var fullVersionString: String { static var fullVersionString: String {
"Version \(displayString) (\(buildNumber))" "Version \(displayString) (\(buildNumber))"
} }
+1 -1
View File
@@ -21,7 +21,7 @@ Outline's web app is great, but there's no native Apple client with full editing
## Requirements ## Requirements
- Xcode 27+ (currently developed against an Xcode 27 beta — this is a hard minimum, not a suggestion) - Xcode 27+ (currently developed against an Xcode 27 beta — this is a hard minimum, not a suggestion)
- macOS 27+. iOS/iPadOS support is planned but not in the current build (see the note above) — same 27+ minimum will apply once it lands - macOS 14+ to run the app. iOS/iPadOS support is planned but not in the current build (see the note above)
- A self-hosted (or hosted) Outline instance with API access - A self-hosted (or hosted) Outline instance with API access
## Setup ## Setup