filmopen_device
Generated by scripts/package_digest.py; regenerate, never edit.
The device’s identity (Software Specification §6.6b): a P-256 key pair the installation makes the first time it registers, its private half kept in the device’s credential store (CredentialStore.current — DPAPI, the Keychain, the Keystore, the Secret Service; the Portal Specification’s P14), and the device’s id, the SHA-256 of the public half in lower-case hex — not a MAC address, an IMEI or a serial number, which an app can no longer read. Unlike those, the id can prove itself: the device signs with its key.
Flutter. 10 files, 915 lines under lib/; 61 tests in 4 files. Barrel: lib/filmopen_device.dart.
Depends on
Section titled “Depends on”- filmopen_l10n — uses nothing by name the digest could see
- filmopen_platform — uses
CredentialStore,CredentialStoreUnavailable - filmopen_state — uses
DeviceAccount,DeviceRegistration,buildStamp,kFilmOpenSiteUrl,runningPlatformName - filmopen_store — uses
AppLog,LogLevel
Third-party: http, pointycastle.
Used by
Section titled “Used by”filmopen_app
Public API
Section titled “Public API”What the barrel exports, file by file. A name is class, enum, mixin, extension, typedef, a top-level function, getter, setter or variable; under a class, its public constructors, fields, getters, setters and methods.
lib/src/claim_device_name_dialog.dart
Section titled “lib/src/claim_device_name_dialog.dart”- function
Future<bool> claimDeviceName(BuildContext context, {DeviceRegistration? registration, String? hostName})— Makes sure the device has its permanent name before what needs one goes on (§6.6b). - class
ClaimDeviceNameDialog— The dialog that claims the device’s permanent name: the host name proposed, the person’s edit, one claim.const ClaimDeviceNameDialog({super.key, required this.registration, required this.proposal})final DeviceRegistration registration— Where the claim goes.final String proposal— The name the box starts with: the host name reduced to the grammar, or empty.
lib/src/device_key.dart
Section titled “lib/src/device_key.dart”- variable
const kDeviceKeyName— The name the key is kept under in the credential store. - class
DeviceKey— One installation’s key pair.static DeviceKey? fromPrivateBytes(List<int> bytes)— The key whose private scalar is [bytes], 32 bytes big-endian.static DeviceKey generate([Random? random])— A new key from [random],Random.secure()unless a test gives one: 32 bytes drawn again until they are a scalar of the curve, which is almost always the first time.static DeviceKey? fromStoredText(String text)— The key kept as [text] (what [storedText] wrote), or null when it is not one.final Uint8List publicKey— The public half: the 65-byte uncompressed SEC1 point,0x04 \|\| X \|\| Y.final String id— The device’s id: the SHA-256 of [publicKey], 64 lower-case hex digits (K2).final String publicKeyText— [publicKey] as the website takes it: canonical unpadded base64url, 87 characters (K3).String get storedText— What the credential store keeps: the private scalar, 32 bytes, as canonical unpadded base64url.String sign(String text)— [text]’s UTF-8 signed with ECDSA and SHA-256, as the raw 64-byter \|\| sin canonical unpadded base64url, 86 characters — never ASN.1 DER (K4).
- function
bool verifyDeviceSignature({required List<int> publicKey, required String text, required String signature})— Whether [signature] (rawr \|\| s, 86 characters of base64url) is [publicKey]’s over [text], taking only what the website takes: a 65-byte uncompressed point on the curve and a canonical signature. - function
String deviceRegistrationProofText({ required String origin, required String account, required String device, required String signedAt, required St…— The six lines a registration’s proof signs, joined by one\nwith no trailing newline (the contract’sPUT /v1/devices/{id}). - function
String sha256Hex(List<int> bytes)— The SHA-256 of [bytes] in lower-case hex. - function
String base64UrlText(List<int> bytes)— [bytes] as canonical unpadded base64url: what every standard encoder emits, less its=. - function
Uint8List? base64UrlBytes(String text)— The bytes of unpadded base64url [text], or null when it is not that.
lib/src/device_key_store.dart
Section titled “lib/src/device_key_store.dart”- enum
DeviceKeyProblem— Why no key could be had, as the log names it.- values:
noStore,unreadable,unwritable,emptyStore
- values:
- class
DeviceKeyUnavailable— No key could be had; [problem] says why.const DeviceKeyUnavailable(this.problem)final DeviceKeyProblem problem
- function
Future<({DeviceKey key, bool made, bool replaced})> openDeviceKey(CredentialStore store)— This installation’s key from [store]: the one it keeps, or a new one made and kept when it keeps none.
lib/src/device_name_stub.dart
Section titled “lib/src/device_name_stub.dart”- function
String? deviceName()— The web suggests no name: a browser has none of its own to give.
lib/src/device_name_text.dart
Section titled “lib/src/device_name_text.dart”- function
String? deviceNameText(String text)— [text] as a name the website takes (its contract’sname).
lib/src/device_registrar.dart
Section titled “lib/src/device_registrar.dart”- variable
const kDevicePlatforms— The platforms the website knows (its contract’s closed list, K13); another is refused there, so it is not asked. - class
DeviceRegistrar— The seam’s real implementation, installed bylib/main.dartoff the web: once per sign-in, once per launch, and invisible.DeviceRegistrar({ required this.origin, required this.platform, required this.appVersion, required this.buildStamp, this.name, http.Client? client,…final String origin— The site’s origin,https://dev.filmopen.aiorhttps://filmopen.ai(kFilmOpenSiteUrl).final String platform—runningPlatformName().final String appVersion—0.1.0+dev: the version and the build.final String buildStamp— The build’s stamp (§6.6a).final String? name— The name the device calls itself, or null (deviceName()).final Duration timeout— How long a request may take before it counts as not made.final void Function()? onRegistered— Told once the website took the device, or answered its name, so that what reads [registeredDevice] and [slug] asks again.Future<void> get idle— The chain of requests settles; for the tests.
lib/src/device_slug.dart
Section titled “lib/src/device_slug.dart”- function
bool isDeviceSlug(String text)— Whether [text] has the website’s grammar for a slug:^[a-z0-9][a-z0-9-]{2,31}$. - function
String proposeDeviceSlug(String? hostName)— The slug proposed for a device called [hostName]: lowered, every run of other characters one dash, no dash at either end, at most 32 characters; empty where fewer than three are left. - class
DeviceSlugStore— Where the claimed slug is kept: the app’s preferences, under<accountId>/<deviceId>/slug.String? read(String key)— The value under [key], or null.Future<void> write(String key, String? value)— Keeps [value] under [key]; null removes it.
- class
MemoryDeviceSlugStore— A [DeviceSlugStore] that lasts as long as the process: the tests’, and a build that keeps no preferences.
Internal
Section titled “Internal”Files under lib/ the barrel does not reach; nothing outside the package may import them.
lib/src/device_name_io.dart:deviceName