Repository navigation
halvorai-ingest 0.5.0: device helpers for Flutter apps - #8
Open
hedge-mustafa wants to merge 1 commit into
Open
hedge-mustafa wants to merge 1 commit into
hedge-mustafa wants to merge 1 commit into
Conversation
Apps built with halvorai_ingest_flutter sign events on the phone and never hold an API key; the customer's backend registers each install's key and forwards its batches. halvorai_ingest.device provides that half, with the same behaviour as @halvorai/ingest/device 0.4.0: - register_device_source(_async): registers an install's public Ed25519 key with POST /v1/sources; a key with d is refused. - forward_envelopes(_async): checks each event's owner against the signed-in user and its environment against the key, then passes the body to POST /v1/events byte for byte and returns HalvorAI's answer unchanged. Refusals use HalvorAI's error format. - README: a FastAPI example of both routes. init now registers its source through the same code (sources.py); a refused registration still raises RuntimeError. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Mobile apps built with
halvorai_ingest_fluttersign events on the phone, with a key each install makes for itself. The app never holds an API key. The customer's backend has two jobs:This PR adds that backend half: items SDK-1 to SDK-3 in the Flutter backend requirements. The API-side items are separate. The same change is going into the other server SDK (halvorAI/ingest-js) so both behave the same.
What's added:
halvorai_ingest.device(0.5.0)register_device_source/register_device_source_async:d.kty,crvandxtoPOST /v1/sources, and returns thesrc_id.forward_envelopes/forward_envelopes_async:owner.idis the signed-in user, and that itsenvironmentmatches the API key.POST /v1/eventsbyte for byte. It's parsed only for the checks, because re-serializing could change bytes the device signed.resultsfrom them.Refusals use HalvorAI's error format (
{"error":{"code","message"}}), so the Flutter SDK reports the code asserverCode. The status tells the app what to do:invalid_requestpayload_too_largeowner_mismatch,environment_mismatchupstream_error(HalvorAI unreachable)initnow registers its source through the same code (sources.py). A refused registration still raisesRuntimeError(nowSourceRegistrationError, a subclass).Tested
uv run mypy(strict),uv run pytest(164 tests, 19 new) on the default Python and on 3.10.End to end with the Dart SDK. A local backend built from these helpers sat in front of a fake HalvorAI, which verifies every forwarded signature against the key registered for its source. The client was
halvorai_ingest(Dart), doing exactly what the Flutter package does: registering per the provisioning contract and delivering throughForwardingTransport. Results:src_id; a private key is refused with 400.owner_mismatch.The same run passes against the other SDK's helpers.
Not in this PR
kind: "device"and paging for many sourcesDELETE /v1/sources/{id}revokeDeviceSource(SDK-5): waits for thatDELETEendpoint.unconfirmedrules. They aren't needed for Flutter to work, and are a separate change.Please don't merge until it has been reviewed.
🤖 Generated with Claude Code