swan

For builders

Your app reviews.
Swan rechecks.

Put Swan in the application that owns capture and sending. Your assistant proposes an action. Your trusted review screen shows the exact content and recipient. Swan checks that approval again right before the send.

Run Swan on your computer

Download the Swan 0.4 Python package into a folder. With Python 3.10 or newer, run these commands from that folder:

python3 -m venv .venv
.venv/bin/python -m pip install ./swan_wearable_security-0.4.0-py3-none-any.whl
.venv/bin/swan-demo --case valid_upload
.venv/bin/swan-demo --case recipient_drift

The demo uses a fixed sample and a private receiver on your computer. It checks what arrived, then closes the receiver. It needs no camera or account. Download the package.

Connect your application

Your application supplies the camera bytes, their real capture time, its bystander decision, and a trusted review screen. This is the connection pattern; the runnable demo above supplies those pieces locally.

from swan import CaptureGuard, HttpDestination

recipient = HttpDestination("https://your-service.example/observation")
guard = CaptureGuard(
    max_capture_age=30,
    allowed_destinations=(recipient,),
)

# Call these from trusted device and permission callbacks.
guard.connect("selected-device")
guard.permission("camera", True)
epoch = guard.start_stream()

def prepare_review(picture_bytes, captured_at, bystander_status):
    frame = guard.observe_frame(
        epoch, picture_bytes,
        captured_at=captured_at,
        bystanders=bystander_status,
    )
    return guard.propose(
        frame, picture_bytes, recipient,
        payload_kind="source",
    )

# Your trusted review screen shows picture_bytes and recipient.
# Call this function only from its confirmed human-approval callback.
def on_person_approved(proposal, picture_bytes):
    approval = guard.approve(proposal)
    return guard.dispatch(
        approval, proposal, picture_bytes, recipient,
    )

The same exact recipient must be allowed, reviewed, and sent. captured_at comes from the source using the guard's monotonic clock; callback arrival is not capture time. Your application decides bystander status. If the person declines, call guard.cancel(proposal). Run the network send off the screen's main thread.

Know whether it arrived

Basic dispatch can report that the receiver answered, but a lost answer leaves delivery uncertain. Swan 0.4 can also check a durable receiver record. To use this, your authenticated service must save a receipt after POST /observation and return the same record from GET /observation/receipts/{id}. Save the operation ID before sending so the application can check again after a restart.

from swan import ReceiptClient, dispatch_with_receipt, new_operation_id

# Use these instead of the two functions above when your receiver
# supports durable receipts. save_intent is your app's durable callback.
def prepare_confirmed_review(
    picture_bytes, captured_at, bystander_status, save_intent,
):
    frame = guard.observe_frame(
        epoch, picture_bytes,
        captured_at=captured_at, bystanders=bystander_status,
    )
    operation_id = new_operation_id()
    save_intent(operation_id, recipient, picture_bytes)
    return guard.propose(
        frame, picture_bytes, recipient,
        operation_id=operation_id, payload_kind="source",
    )

# Call only after your trusted screen confirms human approval.
def on_person_approved_with_receipt(
    proposal, picture_bytes, your_trusted_auth_header,
):
    approval = guard.approve(proposal)
    client = ReceiptClient(
        recipient, namespace="your-account",
        authorization=your_trusted_auth_header,
    )
    return dispatch_with_receipt(
        guard, approval, proposal, picture_bytes, client,
    )

The receipt route must authenticate the same account as the upload route. your_trusted_auth_header is an application-owned function that supplies the Authorization header; Swan does not store credentials or create the receiver. A matching receipt confirms the receiver stored the exact payload record. It does not confirm later business actions.

One result. A clear next step.

ResultWhat happenedWhat your app does
blockedThis dispatch did not call the sender.Explain the change. Ask for a fresh review.
acceptedThe service returned HTTP success.Read the service's own record before claiming completion.
confirmedA matching stored receipt was read back.Show that the receiver recorded the exact send.
delivery_unknownDelivery could not be confirmed.Check the receiver. Never retry automatically.

Keep the boundary intact

What exists today

The downloadable Python 0.4 library includes the guard and optional receipt checks. An Android callback adapter is implemented separately. Your application provides its own authenticated review screen and receiver; neither is supplied as a hosted service here.

Earlier public source  |  Back to the demo