Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion appleApp/FTW/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,46 @@
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeUserID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeDeviceID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeOtherDataTypes</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
</array>
</dict>
</array>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
Expand Down
8 changes: 4 additions & 4 deletions appleApp/FTWKit/Sources/FTWKit/Identity/CloudGrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import Observation
@Observable
@MainActor
public final class CloudConsent {
nonisolated public static let policy = "ftw-cloud-2026-10-v2"
nonisolated public static let statsPolicy = "ftw-project-stats-2026-10-v2"
nonisolated public static let policy = "ftw-cloud-2026-10-v3"
nonisolated public static let statsPolicy = "ftw-project-stats-2026-10-v3"
nonisolated public static let statisticsDetails = "Recorded hourly energy, configured battery capacity, battery and charger power limits, and solar capacity help Sourceful improve FTW and publish group totals. Values are rounded to 10 Wh or W. No names, addresses or device ids."
nonisolated public static let statisticsPrivacy = "Sourceful links reports to your Cloud home for deletion. They are not anonymous and stay for 13 months. Public values need at least 20 homes, with no home above 30% of a sum. Turning FTW Cloud off deletes unpublished reports when the box reaches Cloud; published totals remain."
nonisolated public static let statisticsPrivacy = "Sourceful links reports to your Cloud home for deletion. They are not anonymous and stay for 48 hours. Public values need at least 20 homes, with no home above 30% of a sum. Turning FTW Cloud off deletes unpublished reports when the box reaches Cloud; published totals remain."
nonisolated public static let statisticsWaiting = "Hourly collection waits for privacy review and policy activation. Your choice can be saved now; no hourly report leaves before approval."
nonisolated public static let included = "Everyone using FTW Cloud contributes to project statistics. There is no separate statistics switch. If you do not want to contribute, use FTW locally without Cloud. Local users can choose to share statistics without enabling remote access."

Expand Down Expand Up @@ -164,7 +164,7 @@ public enum CloudWords {
static let sv: [String: String] = [
"Demo: no reports leave this phone.": "Demo: inga rapporter lämnar telefonen.",
CloudConsent.statisticsDetails: "Dela registrerad timenergi, inställd batterikapacitet, effektgränser för batterier och laddare samt solkapacitet med Sourceful för att förbättra FTW och publicera gruppsummor. Värden avrundas till 10 Wh eller W. Inga namn, adresser eller enhets-id:n.",
CloudConsent.statisticsPrivacy: "Sourceful kopplar rapporterna till ditt Cloud-hem för att kunna radera dem. De är inte anonyma och sparas i 13 månader. Publika värden kräver minst 20 hem och att inget hem står för mer än 30 procent av summan. Stänger du av FTW Cloud raderas opublicerade rapporter när boxen når Cloud; publicerade gruppsummor finns kvar.",
CloudConsent.statisticsPrivacy: "Sourceful kopplar rapporterna till ditt Cloud-hem för att kunna radera dem. De är inte anonyma och sparas i 48 timmar. Publika värden kräver minst 20 hem och att inget hem står för mer än 30 procent av summan. Stänger du av FTW Cloud raderas opublicerade rapporter när boxen når Cloud; publicerade gruppsummor finns kvar.",
CloudConsent.statisticsWaiting: "Timinsamlingen väntar på integritetsgranskning och aktivering. Ditt val kan sparas nu; ingen timrapport lämnar boxen före godkännandet.",
CloudConsent.included: "Alla som använder FTW Cloud bidrar till projektstatistik. Det finns inget separat statistikval. Vill du inte bidra använder du FTW lokalt utan Cloud. Lokala användare kan välja att dela statistik utan att slå på fjärråtkomst.",
"Accept Cloud terms": "Godkänn Cloud-villkoren",
Expand Down
4 changes: 2 additions & 2 deletions appleApp/FTWKit/Tests/FTWKitTests/CloudConsentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import Testing
func defaults() throws -> UserDefaults {
try #require(UserDefaults(suiteName: "ftw-consent-\(UUID().uuidString)"))
}
static let currentPolicy = #"{"policy":"ftw-project-stats-2026-10-v2","cloud_policy":"ftw-cloud-2026-10-v2","cloud_includes_statistics":true,"available":false}"#
static let granted = #"{"state":"on","policy":"ftw-cloud-2026-10-v2","cloudPolicy":"ftw-cloud-2026-10-v2","cloudTermsAccepted":true,"statisticsPolicy":"ftw-project-stats-2026-10-v2","statisticsActive":true,"connected":true}"#
static let currentPolicy = #"{"policy":"ftw-project-stats-2026-10-v3","cloud_policy":"ftw-cloud-2026-10-v3","cloud_includes_statistics":true,"available":false}"#
static let granted = #"{"state":"on","policy":"ftw-cloud-2026-10-v3","cloudPolicy":"ftw-cloud-2026-10-v3","cloudTermsAccepted":true,"statisticsPolicy":"ftw-project-stats-2026-10-v3","statisticsActive":true,"connected":true}"#
func home(role: String = Contract.roleOwner, caps: [String] = [Contract.capCloudLink, Contract.capAPIPassthrough], cloud: Bool = false) async throws -> CloudSite {
let w = try CloudSite()
w.open()
Expand Down
2 changes: 1 addition & 1 deletion appleApp/FTWKit/Tests/FTWKitTests/CloudWireTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func cloudSign(_ key: P256.Signing.PrivateKey, home: String, t: String, b: Bytes
let v = try CloudVectors.load()
let boxPK = Bytes(hex: v.boxKey.pk)
let servicePK = Bytes(hex: v.serviceKey.pk)
#expect(v.messages.count == 27)
#expect(v.messages.count == 32)

for m in v.messages {
let frame = Bytes(hex: m.frame)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,31 @@
"name": "lp car tapped",
"envelope": "a361625901ada7637365711264626f6f7450b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b06677616c6c4d731b000001a130d7f20868666565646261636b8068757074696d654d731a00013c686a636f6e74726f6c52657619032e6a6c6f6164706f696e747381b8186269646b6a33485a4f524e43574873637372636b4455595757516d6e2d586765626f6f7374f46563617249646b464e4b6962697466655530666d616e75616cf6666e6578745768f666706f776572570067706c7567676564f56773657373696f6e703764316630633261396233653466353067736f6341676553190221696e657874456e644d73f669726561647942794d731b000001a133a1bc8069726563757272696e67f56973657373696f6e57680069736f63536f757263656776656869636c656a636f6d6d616e64656457f66b6e65787453746172744d73f66b706c616e50656e64696e67f46b736f635065726d696c6c65188c6b737572706c75734f6e6c79f46c677269644465666572726564f46e7461726765745065726d696c6c651903206f6361724964656e7469666965644279637461706f636f6d6d616e646564526561736f6e64706c616e6174626c7063736967584089b4a6faa2af341cdc4da9ad0247aa2135f40e1aec94554cf1855392d22412cb2191b2a594084e4490faada200f68abbdcdd80b7b0bc3e7fb4ff65e5572f3fcf",
"datagram": false
},
{
"name": "roster browser notice",
"envelope": "a361625901e7ab637365711364626f6f7450b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b06474746c531a00015180656772616e74a4626964406673636f7065738068707572706f736573806a636f6e74726f6c6c657260656e6f697365406677616c6c4d731b000001a130d7f5f0676465766963657381a66269646762726f77736572636b6579582055555555555555555555555555555555555555555555555555555555555555556374756ef464726f6c65656f776e65726565706f6368016673636f706573816f6674772e6576656e74732e726561646770656e64696e6780677765627075736881a662637458806666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666626964736f70617175652d737562736372697074696f6e636465766762726f77736572646175746870766170696420626f782d7369676e65646565706f63680168656e64706f696e74781b68747470733a2f2f707573682e6578616d706c652f6f706171756568757074696d654d731a0001405069726f7374657253657105617466726f737465726373696758409c84115970bee55473418d660236e759a1c818333cc1a1c0d7b5aba44d0eaa2f9fc08e617b72d788232ca0bd46e0d4602074c27222725d7c8d7e83c54ea340c9",
"datagram": false
},
{
"name": "statistics service ready",
"envelope": "a36162588da563656b6d582022222222222222222222222222222222222222222222222222222222222222226468617665a068626f784e6f6e63655820333333333333333333333333333333333333333333333333333333333333333369726f73746572536571046b7374617473506f6c696379781c6674772d70726f6a6563742d73746174732d323032362d31302d763361746868656c6c6f5f6f6b637369675840790390a99204558bb3d80cbbc6a436d40548f3d3e865cb4b71329c2f09b2d3abb5f1814526280ba8aac35113d21ae1dd715950bf2ccf7a66b30484cfc0d1b406",
"datagram": false
},
{
"name": "statistics closed hour",
"envelope": "a3616258b8a8637365711464626f6f7450b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b066686f75724d731b000001a130a0b18066706f6c696379781c6674772d70726f6a6563742d73746174732d323032362d31302d76336677616c6c4d731b000001a130d7f9d8676d657472696373a270666c657869626c655f706f7765725f77192af87070765f67656e65726174696f6e5f776818786773746174734964508888888888888888888888888888888868757074696d654d731a000144386174657374617473637369675840134ad340a1190a23d332c1cd39aabafb2a8e88a6393870feb391a7178b39302ff8a38ec7fc1ba9e4a658b8d8d470176f2b979df63dbc258f31450268eb33721f",
"datagram": false
},
{
"name": "statistics only roster",
"envelope": "a36162590133aa637365711764626f6f7450b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b06474746c531a00015180656772616e74a862696450444444444444444444444444444444446673636f706573806773746174734964508888888888888888888888888888888868707572706f736573816573746174736a636f6e74726f6c6c657269736f7572636566756c6b7374617473506f6c696379781c6674772d70726f6a6563742d73746174732d323032362d31302d76336b7465726d73506f6c696379781c6674772d70726f6a6563742d73746174732d323032362d31302d76336c737461747353696e63654d731b000001a13069c300656e6f697365406677616c6c4d731b000001a130d805906764657669636573806770656e64696e678068757074696d654d731a00014ff069726f7374657253657107617466726f73746572637369675840002b962e9bdd240655dffcc799cacb23414e2f7fd7398209bb9d78b18020a32457bbe8efee41cd35d02ce021940309891e4b0aeacaa6bdcadacd6397b1c4006b",
"datagram": false
},
{
"name": "roster statistics consent",
"envelope": "a36162590130aa637365711564626f6f7450b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b06474746c531a00015180656772616e74a862696450444444444444444444444444444444446673636f706573806773746174734964508888888888888888888888888888888868707572706f736573826573657276656573746174736a636f6e74726f6c6c657269736f7572636566756c6b7374617473506f6c696379781c6674772d70726f6a6563742d73746174732d323032362d31302d76336b7465726d73506f6c696379746674772d636c6f75642d323032362d31302d76336c737461747353696e63654d731b000001a13069c300656e6f697365406677616c6c4d731b000001a130d7fdc06764657669636573806770656e64696e678068757074696d654d731a0001482069726f7374657253657106617466726f7374657263736967584059638b7a4468f8a7ae3210d8b83bf5f03adbdfec68c46bf4a8f56e0c7b99918927d12e9c6eea548e3f3d3f1bfd615371cd5d7bbb00c27278ef08a3abdca482d9",
"datagram": false
}
],
"notes": {
Expand Down
Loading
Loading