
Introduction
Welcome! This book serves as the spot that the Worldcoin Project hosts its documentation for developing software for the orb.
It also provides an inside look at our development practices, which helps increase transparency of the project and provide foundations for other contributors to the project to build on top of.
Who is this for?
The target audience of this documentation is for contributors to the orb-software repo or any of the other open source repos that pertain to the orb. We plan to accept contributions at a later date, but do not have bandwidth to review PRs currently.
Likewise, we are providing source code and documentation for the benefit of the community, but cannot commit to any SemVer or API stability guarantees. Be warned: we may change things in a backwards-incompatible way at any time!
Where is the code?
See the orb-software repo for the code.
This is a living document. If you are a contributor and wish to improve the documentation, simply open a PR! The source code for the mdBook lives here.
However, spam/noise/typo PRs will be ignored. Especially those from bots. Do not farm green github squares from us.
Initial repo setup
To be able to build the code, there is some first-time setup required. There are two options:
Set up nix + direnv (the developer environment)
We use nix to manage all of the dependencies during development. While most of the software can use convnetional rust tools like cargo, we do have a few additional dependencies. Instead of apt-installing them, we use nix as the package manager, and use direnv to handle automatically activating a developer shell. The process to install and configure these two tools is as follows:
- Install nix. This works for both mac and linux, if you are using a windows machine, you must first set up WSL2.
- Ensure that you have these lines in your
~/.config/nix/nix.confor/etc/nix/nix.conf. This is done automatically by the above installer:
You can check that things work by runningexperimental-features = nix-command flakes max-jobs = autonix run nixpkgs#hello - Install direnv:
nix profile install nixpkgs#direnv - Hook direnv into your shell.
- Set up your personalized .envrc file by running
cp .envrc.example .envrc. You can customize this file if you wish. We recommend filling in your cachix token if you have one. If prompted, don't rundirenv allowyet, follow step 6 first. Otherwise you'll get a bunch of errors. - Follow the instructions on vendoring proprietary SDKs in the subsequent section.
- Run
direnv allowin the repository's root directory. Direnv will then automatically use the .envrc file you set up any time youcdinto the directory. - If you are on macos, run the following:
brew install dbus brew services start dbus - Install git lfs:
git lfs install git lfs pull
Set up devcontainer
If you are using devcontainer with with or without vscode, you could use the provided devcontainer.json.
- Download the Seek Thermal Sdk and save it in .devcontainer/Seek_Thermal_SDK_4.1.0.0.zip
- Fire-up your devcontainer
Vendoring proprietary SDKs
Although all of Worldcoin's code in the orb-software repo is open source, some of the sensors on the orb rely on proprietary SDKs provided by their hardware vendors. Luckily, these are accessible without any cost, they are just annoying to get and are not themselves open source.
To get started, you will need to download these SDKs. The process for this depends on if you are officially affiliated with Worldcoin.
If you have access to Worldcoin private repos
- Create a personal access token from github to allow you to use private git repos over HTTPS.
- Append the following to your
~/.config/nix/nix.conf:access-tokens = github.com=github_pat_YOUR_ACCESS_TOKEN_HERE - Test everything works so far by running
nix flake metadata github:worldcoin/priv-orb-core. You should see a tree of info. If not, you probably don't have your personal access token set up right - post in slack for help.
If you don't have access to Worldcoin private repos
- Go to https://developer.thermal.com and create a developer account. Getting the SDK can take several days for Seek Thermal to approve access. In the meantime, you can skip steps 2 and 3.
- Download the 4.1.0.0 version of the SDK (its in the developer forums).
- Extract its contents, and note down the dir that contains the
Seek_Thermal_SDK_4.1.0.0dir. - modify your
.envrclike this:use flake . --override-input seekSdk "PATH_FROM_STEP_3". If you don't yet have access to the SDK, just provide a path to an empty directory.
Setting up AWS Credentials
[!NOTE] This section only applies to developers affiliated with the worldcoin organization.
Certain tools, including orb-tools, orb-hil, orb-bidiff-cli,
cargo x optee ta sign and the official aws cli require setting up AWS credentials to
use them.
While its always possible to export the credentials on the command line, its typically
easier to leverage AWS's official "profile" system. Profiles are controled with the
AWS_PROFILE environment variable, and configured under the ~/.aws directory.
For the intended contents of ~/.aws/config, see the internal docs.
You can now chose the appropriate aws profile for any CLI tool by passing the
AWS_PROFILE=<profilename> env var in any aws-related tasks.
The available profiles above are:
hilfor theorb-hilclibidiff-{stage,prod}to bidiff OTAs with theorb-bidiff-clitrustzone-{stage,prod}to sign optee TAs withcargo x optee ta sign
Examples
For example, to use the HIL CLI:
AWS_PROFILE=hil aws sso login --use-device-code
AWS_PROFILE=hil cargo run -p orb-hil
To diff prod OTAs:
AWS_PROFILE=bidiff-prod aws sso login --use-device-code
AWS_PROFILE=bidiff-prod cargo run -p orb-bidiff-cli
How to develop and build code
Make sure you followed the first time setup instructions.
Building
We use cargo zigbuild for most things. The following cross-compiles a binary
in the foobar crate to the orb. Replace foobar with the crate that you wish
to build:
cargo zigbuild --target aarch64-unknown-linux-gnu --release -p foobar
You can also build code faster with cargo check, since it skips the linking
step. Try running cargo check -p foobar.
Testing the code
Unlike building the code, tests are expected to run on the same target as the host. But not all tests are possible on every target.
IF it is supported, you can run cargo x t -p foobar. Use
cargo x tw -p foobar to watch and rerun the tests. Both aliases run nextest
with all features enabled. Support varies from crate to crate.
Running tests locally
Run cargo x t --all-targets -p foobar for any crate named foobar, or
cargo x t --workspace --all-targets to test all crates. Use cargo x tw with
the same arguments to watch and rerun tests. Both aliases run nextest with all
features enabled. Some of our crates can only build when targeting Linux, so on
macOS you will need to use the -p version or one of the Docker runners below.
You can also resort to cross compiling to linux and then running your tests in docker. There are two ways to do this:
Using a container based on a Dockerfile
A limited subset of tests can use a container built from a Dockerfile at
docker/Dockerfile. You can choose to run tests this way with the following command:
RUSTFLAGS='--cfg docker_runner' cargo x t --target aarch64-unknown-linux-gnu --workspace --all-targets
Using a container built from nix directly
More (possibly all) tests can be run by using a container built using
docker-tools. However, this requires you to have a linux remote
builder runner for nix set up. The easiest way to do this is to use the
linux-builder feature of nix-darwin. After
setting up nix-darwin and enabling the linux-builder
setting in your configuration.nix, you can run:
RUSTFLAGS='--cfg nix_docker_runner' cargo x t --target aarch64-unknown-linux-gnu --workspace --all-targets
Note that the only difference between this command and the other one is that the
config flag for cargo is prefixed with nix_.
Running the code on an orb
For binaries that are intended to run on the orb, you can take your
cross-compiled binary, and scp it onto the orb. You can either use teleport (if
you have access) via tsh scp or you can get the orb's ip address and directly
scp it on, with the worldcoin user.
If you choose the scp route without teleport, you will need to know the
password for the worldcoin user. Note that this password is only for dev
orbs, orbs used in prod are not accessible without teleport and logging in with
a password is disabled.
Debugging
Tokio Console
Some of the binaries have support for tokio console. This is
useful when debugging async code. Arguably the most useful thing to use it for
is to see things like histograms of poll() latencies, which can reveal when
one is accidentally blocking in async code. Double check that the binary you
wish to debug actually supports tokio console - support has to be manually
added, it isn't magically available by default.
To use tokio console, you will need to scp a cross-compiled tokio-console
binary to the orb. To do this, just clone the repo and use
cargo zigbuild --target aarch64-unknown-linux-gnu --release --bin tokio-console, then scp it over.
Note: tokio-console supports remote debugging via grpc, but I haven't figured out how to get the orb to allow that yet - I assume we have a firewall in place to prevent arbitrary tcp access, even in dev orbs.
Then, you must build the binary you want to debug unstable tokio features enabled. To do this, uncomment the line in .cargo/config.toml about tokio unstable.
Finally, make sure that the binary has the appropriate RUST_LOG level set up.
try using RUST_LOG="info,tokio=trace,runtime=trace".
Finally, run your compiled binary and the compiled tokio-console binary on
the orb. You should see a nice TUI.
Note that it is recommended but not required to have symbols present to improve the readability of debugging.
Android
Cross-compiling this workspace to aarch64-linux-android, and packaging
binaries into signed .apex files.
Setup
Enter the dev shell (nix develop or direnv) - it wires up the NDK
toolchain env vars automatically. Nothing else to install.
Build for Android
cargo x android-build # debug
cargo x android-build --release
Builds the whole workspace for aarch64-linux-android, skipping crates
that don't support it (see [package.metadata.orb] unsupported_targets
in their Cargo.toml - usually dbus/systemd/gstreamer-dependent crates).
Package into .apex
cargo x android-apex # every crate
cargo x android-apex orb-foo # just one crate
cargo x android-apex --release
Requires an x86_64-linux host and nix on PATH (fetches/builds the
build-apex flake package on first run). Output lands in
target/android-apex/<crate>.apex, signed with AOSP's public test
key - never a real release signature.
Install onto a device
cargo x android-deploy # every crate
cargo x android-deploy orb-foo # just one crate
cargo x android-deploy orb-foo --release
Runs android-apex under the hood, then installs each resulting .apex via
adb install -t -r -g --force-non-staged, so it's usable immediately - no
reboot required.
Needs a device reachable over adb (same x86_64-linux + nix
requirement as android-apex also applies here).
Gotchas
- Not every crate builds for Android.
- The manifest name, init script, and SELinux context are still
placeholders (see TODOs in
xtask/src/cmd/android.rs) - the.apexinstalls fine, but the packaged daemon won't actually start under init on a real device yet.
How we do open source
Worldcoin is committed to building a fully open source, decentralized ecosystem. In service of this goal, the entirety of the orb-software repo is open source under an MIT/Apache 2.0 dual license. You can read more about the project's open sourcing efforts here.
All source code for the Worldcoin Project lives under the worldcoin github organizaton.
Overview of private repos
To the maximum extent possible, we put all public code in the orb-software and orb-firmware repos. But we also maintain private repos, which contain code that is responsible for fraud detection or uses third party SDKs that we do not have a license to open source.
The most notable private repos are:
- priv-orb-firmware. This repo contains the fraud sensitive parts of the firmware. It consumes the public orb-firmware repo as a dpenedency.
- orb-internal. This repo contains the fraud sensitive parts of the user-space software. It consumes the public orb-software repo as a dependency.
- priv-orb-core. This repo is the mainline branch of
orb-core. Unlike the other repos, this is a fork of its public counterpart, orb-core. The public repo is therefore inherently less up to date and doesn't retain git history, as its code has all fraud-related codepaths manually deleted. One of the long-term goals is for these two repos to become un-forked, and most code consolidated intoorb-softwareso that we can transition to developing orb-core directly in the open. - trustzone. This repo contains code related to the secure operating system OP-TEE that runs alongside linux inside ARM TrustZone. We plan to open source the OP-TEE CAs and TAs at some point in the future.-
- orb-os. This repo is where we build the operating system image that runs on the orb. It consumes artifacts from all the other repos to assemble one final image.
Over-The-Air Updates (OTAs)
Overview of software components
The OTA system for the orb is comprised of several parts. All components are FOSS unless stated otherwise. Backend infrastructure is owned by Worldcoin Foundation and operated by Tools For Humanity, unless otherwise noted.
It is a long term goal to make these components FOSS, and decentralize them as much as possible.
OTA Consumption (On the orb):
orb-update-agentbinary.orb-update-verifierbinary.
OTA Production (Backend)
orb-osrepo: Not yet FOSS 😢. Contains build scripts and CI to produce the custom debian based linux distro we ship on orbs.orb-bidiff-cli: Produces binary diffs of OTAs for download size reduction.orb-updates-lambda: Not FOSS 😢. Legacy golang lambda that runs whenorb-osbuilds an OTA, to post-process it.orb-manager: Not FOSS 😢. Legacy golang endpoints for OTA updates being migrated toorb-fleet-backend.
OTA Consumption (Backend)
orb-manager: see above.orb-fleet-backend: Not FOSS 😢. New rust/axum service that will manage orbs.- AWS S3 buckets: Used to persist orb-os builds, OTAs, and bidiffs.
- MongoDB: Tracks various information about OTAs and which orbs they are assigned to.
OTA structure
OTAs are comprised of a claim.json, and a list of binary files which we refer to as
"components".
Claim structure
The claim.json can also be divided into three main parts, the manifest and the sources.
- The
manifestfield, which contains metadata about how a component should be installed, as well as integrity information such as the hash of the component, its size, etc. - The
sourcesfield, which contains metadata about the compressed version of components, along with where they can be downloaded. These also have hashes and other integrity information. - The
signaturefield, which enables the update agent to verify that the manifest has not been tampered with. This signature protects only the manifest, it does not protect the rest of the claim or the sources. Note that most of the orbs secure boot guarantees actually come from other places like dm-verity and our secure boot architecture, not from this manifest signature. In other words, the manifest signature is a nice "bonus" security measure.
When stored on s3, typically all of the compressed components (the sources), as well as the claim.json, are stored together in a "directory".
What is a component?
Once the source for a component is downloaded and potentially decompressed, it will be
installed differently depending on the component type. Typically these components are
things like partitions that should be dded to disk, firmware blobs to be sent over
CAN, etc.
For the most comprehensive documentation, see the Component enum.
How do Partial OTAs work?
A partial OTA is a method of reducing the size of an OTA by sending only a subset of the full set of components in an OTA. Partial OTAs rely on shaky promises of reproducibility in orb-os, where we hope that certain partitions that the build produced didn't change, and therefore we can get away with not including the unchanged partitions as components in the OTA.
With the advent of binary diffing, partial OTAs are essentially unecessary. They are also even less useful on diamond orbs, whose root file system is mostly bundled into a single, really large component instead of multiple overlayfs partitions.
How do Binary Diffs work?
A component that is binary diffed is no different from a regular component, it just has
a different MIME type - application/zstd-bidiff. Like GPT components, these are
essentially just partition contents + the label of the partition. When "extracting" a
bidiff component we:
- inspect the component's label, to find a matching partition on the current booted slot which will become the base against which the patch will be applied.
- stream the component through a zstd decompressor and the
bipatchcrate, writing the result out to the same location on the SSD that any other component source gets extracted to. - Proceed as normal, just like any other extracted component.
Binary Diffing CLI
A full size orb-os image can often be 5-6.5 GiB in size. Binary diffing is used as a compression mechanism, to reduce OTA sizes by only sending to orbs a "binary diff".
What is a Binary Diff
A binary diff is analagous to a diff in git, except instead of operating at the
textual level, it operates at the bit/binary level.
The orb uses the bidiff and bipatch crates to generate and apply binary
diffs, in addition to our own modifications to better handle
squashfs files.
Further documentation on how bidiff, bipatch, and orb-bidiff-squashfs work can be
found in their respective crates.
See also OTA Structure for more information on how binary diffs are represented in an OTA.
How to produce an OTA that uses binary diffs?
You can use either orb-tools bidiff or orb-bidiff-cli - both ways of accessing the
cli are equivalent. Please refer to the documentation of the tool's --help interface
for the most up-to-date docs.
Be sure that your AWS credentials are configured - you can follow the same instructions from orb-hil.
This CLI will be able to retrive the full-size OTAs from several places:
ota://X.Y.Z+whateverto download from s3 via the orb-os OTA version numbers3://foo/bar/to download from s3 via a S3 URI- or a local file path
The CLI will take several minutes to run, and then produces a new OTA directory
which contains all the components and a new, patched claim.json.
To see what the diffing process looks like, see this asciinema recording:
How to get the orb to OTA with a binary diff?
Right now the backend doesn't support binary diffs yet, this is still WIP.
In the meantime, you can scp -r the contents of the directory that orb-bidiff-cli
produced onto your orb, typically onto the ssd at /mnt/scratch/my-ota.
Then invoke the update agent with:
cd /mnt/scratch/my-ota
sudo /usr/local/bin/orb-update-agent \
--nodbus \
--orb-id $ORB_ID \
--update-location /mnt/scratch/my-ota/claim.json
Hardware In Loop
Developing for the orb generally requires access to an orb. To make life easy,
as well as to enable automated tests, we use an x86 linux machine as a host, which
attaches to an orb via a number of hardware peripherals. We created the orb-hil
cli tool to leverage this known hardware setup to perform a number of common,
useful actions.
Getting an x86 Linux Machine
Technically, any x86 linux machine will do. However, we recommend using an ASUS/Intel NUC due to its compact form factor.
The Linux installation needs:
- Access to the various attached usb devices without sudo, i.e. udev rules configured
- Access to serial without sudo
- Various packages (awscli2, usbutils, etc)
- Teleport
- Github self-hosted runner (if using this in CI).
To make this setup easy, we have a nix config that sets all of this up. BUT you could use regular ubuntu, or some other linux distro instead.
orb-hil cli
There is a CLI tool to facilitate hardware-in-loop operations. This tool lives in the orb-software repo and releases can be downloaded here.
It is a single, statically linked CLI tool with lots of features helpful for development:
- Rebooting orbs into either normal or recovery mode
- Flashing orbs (including downloading from S3, extraction, etc)
- Executing commands over serial, SSH, or Teleport
- Automating the login process over serial
Required peripherals
Different orb-hil subcommands require different hardware peripherals. We
strongly recommend at least getting an x86 linux machine and a serial adapter.
Here are the different hardware peripherals necessary for the different
subcommands of orb-hil:
orb-hil flash: x86 linux machineorb-hil reboot: Serial adapter.orb-hil login: Serial adapter.orb-hil cmd: Serial adapter or network access (SSH/Teleport).
Logging in to AWS
The flash subcommand can download S3 urls. To set this up, we recommend following the
instructions to set up aws. Then you can run
AWS_PROFILE=hil aws sso login # refresh your credentials for the hil profile
AWS_PROFILE=hil cargo run -p orb-hil # tell the orb-hil cli to use the hil profile
Software components of the orb
The orb consists of several software components. This section of the book provides a place to describe all of these different components.
See the individual sections in the table of contents to read more.
Orb Core
orb-core contains the core rust application responsible for verifying users'
World IDs.
The binaries controlling the orb are found in src/bin/:
- src/bin/orb-core.rs: the production binary, which runs verifications in the field.
- src/bin/orb-backend-connect.rs: a binary to ensure backend connectivity by scanning a WiFi QR code and establishing the WiFi connection as long as the backend is not reachable.
Code Overview
Overview of the do_signup function:
flowchart TD
A[Start Signup] --> B{Scan Operator QR Code}
B -->|Success| C{Scan User QR Code}
B -->|Failure| Z[End Signup]
C -->|Success| D{Detect Face}
C -->|Failure| Z
D -->|Detected| E[Start Image Notary]
D -->|Not Detected| Z
E --> F[Biometric Capture]
F --> G[Stop Image Notary]
G --> H[Biometric Pipeline]
H --> I{Detect Fraud}
I -->|No Fraud| J[Enroll User]
I -->|Fraud Detected| K[Mark as Fraud]
J -->|Success| L[Mark Signup as Successful]
J -->|Failure| M[Mark Signup as Failed]
K --> N[Upload Debug Report and Opt-in Images]
L --> N
M --> N
N --> Z
State of open sourcing
There are two orb-cores: the public one at worldcoin/orb-core and
the private one at worldcoin/priv-orb-core. Today, the public repo
is a manually stripped down version of the private one. This is done to remove
code paths that could reveal the types of fraud detection that we perform. Long
term, we plan to un-fork these two repos such that the public code lives in
worldcoin/orb-software and the private code is only minimal
additional code, which consumes the public code as a dependency. This will
ensure that most code we develop is done directly in the open, where main
lives in a public repo.
See how we do open source for more context.
Orb Management
This section documents tools and workflows used to generate, and register Orb devices across various platforms.
Included Tools
- Orb Registration Script: A Python script that handles Orb provisioning and registration for both Pearl and Diamond platforms.
Orb Registration Script
A python script for generating and registering Orb devices across both Pearl and Diamond platforms with MongoDB and Core-App.
Overview
The script orb-registration.py (scripts/orb-registration/orb-registration.py) is a rewrite of the original gen-orb-id.sh and register-mongo.sh that supports both Pearl and Diamond orb platforms in a single, dependency-free Python implementation.
Key Features:
- Dual Platform Support: Handles both Pearl (with artifact generation) and Diamond (registration-only) workflows
- Zero Dependencies: Uses only Python standard library - no external packages required
Requirements
Python: Python 3.6 or higher (uses only standard library)
System Dependencies (must be available in PATH):
ssh-keygen- SSH key generationmke2fs- ext4 filesystem creationtune2fs- filesystem tuningmount/umount- image mounting capabilitiesinstall- file installation with permissionssetfacl- ACL supportsync- filesystem synchronizationcloudflared- Cloudflare Access authentication
Environment Variables:
FM_CLI_ORB_MANAGER_INTERNAL_TOKEN- MongoDB bearer token (can be overridden with--mongo-token)HARDWARE_TOKEN_PRODUCTION- Core-App bearer token (can be overridden with--core-token)
Installation
-
Make the script executable:
chmod +x orb-registration.py -
Ensure system dependencies are installed:
# Ubuntu/Debian sudo apt-get install e2fsprogs acl cloudflared -
Set up environment variables:
export FM_CLI_ORB_MANAGER_INTERNAL_TOKEN="your_mongo_token_here" export HARDWARE_TOKEN_PRODUCTION="your_core_app_token_here"
Usage
Basic Command Structure
./orb-registration.py --platform {pearl|diamond} --backend {stage|prod} --release {dev|prod} --hardware-version HARDWARE_VERSION [additional options]
Required Arguments
--platform: Platform type (pearlordiamond)--backend: Backend environment (stageorprod)--release: Release type (devorprod)--hardware-version: Hardware version with platform prefix (e.g.,PEARL_EVT1,DIAMOND_EVT2)
Optional Arguments
--channel: Channel for orb registration (default:generalfor prod,internal-testingfor stage)--mongo-token: MongoDB bearer token (overrides environment variable)--core-token: Core-App bearer token (overrides environment variable)
Pearl Platform Options
--count: Number of orbs to generate (default: 1)
Diamond Platform Options
--input-file: Input file containing orb IDs or orb ID+name pairs--input-format: Format of input file (idsorpairs, default:ids)orb_ids: Direct orb IDs as positional arguments (alternative to--input-file)
Platform-Specific Workflows
Pearl Platform
Pearl orbs require complete artifact generation including SSH keys, persistent images, and registration in both systems.
What Pearl workflow does:
- Generates SSH keypair and derives orb-id (SHA256 hash)
- Registers orb in MongoDB Management API
- Sets orb channel
- Retrieves orb token
- Creates persistent filesystem images (1MB and 10MB variants)
- Installs baseline configuration files
- Generates per-orb artifacts with embedded orb-name and token
- Registers orb in Core-App
Generated artifacts (stored in artifacts/{orb-id}/):
uid- Private SSH keyuid.pub- Public SSH keyorb-name- Assigned orb nametoken- Orb authentication tokenpersistent.img- 1MB persistent filesystem imagepersistent-journaled.img- 10MB persistent filesystem image with journal
Diamond Platform
Diamond orbs only require registration without artifact generation.
What Diamond workflow does:
- Processes orb IDs from input (file or CLI arguments)
- Registers each orb in MongoDB Management API (if using IDs-only format)
- Registers each orb in Core-App
Input formats:
- IDs format: File contains one orb ID per line, script gets orb-name from MongoDB
- Pairs format: File contains
orb-id orb-namepairs, script skips MongoDB registration
Detailed Usage Examples
Pearl Platform Examples
Generate Single Pearl Orb (Stage Environment)
./orb-registration.py \
--platform pearl \
--backend stage \
--release dev \
--hardware-version PEARL_EVT1
Generate Multiple Pearl Orbs (Production Environment)
./orb-registration.py \
--platform pearl \
--backend prod \
--release prod \
--hardware-version PEARL_EVT1 \
--count 10 \
--channel production-batch-1
Output:
- Creates 10 separate artifact directories
- Uses custom channel "production-batch-1"
- Registers all orbs in production systems
Pearl with Custom Tokens
./orb-registration.py \
--platform pearl \
--backend prod \
--release dev \
--hardware-version PEARL_EVT1 \
--count 5 \
--mongo-token "custom_mongo_token" \
--core-token "custom_core_token" \
--channel development
Diamond Platform Examples
Register Diamond Orbs from File (IDs Only)
# Create input file
cat > diamond_orbs.txt << EOF
abc123def456
ghi789jkl012
mno345pqr678
EOF
./orb-registration.py \
--platform diamond \
--backend prod \
--release prod \
--hardware-version DIAMOND_EVT2 \
--input-file diamond_orbs.txt \
--channel diamond-production
What happens:
- Reads orb IDs from
diamond_orbs.txt - Registers each in MongoDB to get orb-name
- Registers each in Core-App
- No artifacts generated
Register Diamond Orbs with Pre-assigned Names
# Create input file with orb-id and orb-name pairs
cat > diamond_pairs.txt << EOF
abc123def456 diamond-orb-001
ghi789jkl012 diamond-orb-002
mno345pqr678 diamond-orb-003
EOF
./orb-registration.py \
--platform diamond \
--backend prod \
--release prod \
--hardware-version DIAMOND_EVT2 \
--input-file diamond_pairs.txt \
--input-format pairs \
--channel diamond-custom
What happens:
- Reads orb-id and orb-name pairs from file
- Skips MongoDB registration (names already provided)
- Registers directly in Core-App
- Uses custom channel "diamond-custom"
Register Diamond Orbs via CLI Arguments
./orb-registration.py \
--platform diamond \
--backend stage \
--release dev \
--hardware-version DIAMOND_EVT2 \
abc123def456 ghi789jkl012 mno345pqr678
What happens:
- Processes orb IDs provided as CLI arguments
- Registers in stage environment
- Uses default stage channel "internal-testing"
File Structure
gen-device-unique/
├── orb-registration.py # Main script
├── build/ # Baseline configuration files
│ ├── components.json
│ ├── calibration.json
│ └── versions.json
├── artifacts/ # Generated Pearl artifacts
│ └── [orb-id]/ # Per-orb artifact directory
│ ├── uid # Private SSH key
│ ├── uid.pub # Public SSH key
│ ├── orb-name # Assigned orb name
│ ├── token # Orb authentication token
│ ├── persistent.img # 1MB filesystem image
│ └── persistent-journaled.img # 10MB filesystem image
└── README.md # This file
Channel Configuration
Stage Environment
- Fixed Channel:
internal-testing - Behavior: Channel cannot be overridden for stage environment
- Usage: Primarily for internal testing and development
Production Environment
- Default Channel:
general - Customizable: Can be overridden with
--channelargument - Usage: Flexible channel assignment for production deployments
Channel Examples:
# Uses default "general" channel
./orb-registration.py --platform pearl --backend prod --release prod --hardware-version PEARL_EVT1
# Uses custom channel
./orb-registration.py --platform pearl --backend prod --release prod --hardware-version PEARL_EVT1 --channel batch-2024-01
# Stage always uses "internal-testing" regardless of --channel
./orb-registration.py --platform pearl --backend stage --release dev --hardware-version PEARL_EVT1 --channel ignored
Error Handling
Common Error Scenarios
Already Registered Orb
[ERROR] Failed to register orb abc123def456 in MongoDB: HTTP 409 Conflict - {"error": "Orb already exists"}
Invalid Authentication
[ERROR] Failed to register orb abc123def456 in MongoDB: HTTP 401 Unauthorized - {"error": "Invalid token"}
Network Issues
[ERROR] Failed to register orb abc123def456 in Core-App: HTTP 500 Internal Server Error - {"error": "Database connection failed"}
Missing Dependencies
[ERROR] Command 'ssh-keygen' not found. Please install OpenSSH client.
API Endpoints
MongoDB Management API
- Stage:
https://management.internal.stage.orb.worldcoin.dev - Production:
https://management.internal.orb.worldcoin.dev
Endpoints used:
POST /api/v1/orbs/{orb_id}- Register orbPOST /api/v1/orbs/{orb_id}/channel- Set channelPOST /api/v1/tokens?orbId={orb_id}- Get token
Core-App API
- Endpoint:
https://api.operator.worldcoin.org/v1/graphql - Method: GraphQL mutation
InsertOrb
Troubleshooting
Common Issues
Permission Errors
# Ensure script is executable
chmod +x orb-registration.py
# Check mount permissions
sudo usermod -a -G disk $USER
Missing Environment Variables
# Check if tokens are set
echo $FM_CLI_ORB_MANAGER_INTERNAL_TOKEN
echo $HARDWARE_TOKEN_PRODUCTION
# Set if missing
export FM_CLI_ORB_MANAGER_INTERNAL_TOKEN="your_token"
export HARDWARE_TOKEN_PRODUCTION="your_token"
Alternatively pass them as input arguments
Cloudflared Issues
# Login to cloudflared
cloudflared access login --quiet https://management.internal.stage.orb.worldcoin.dev
# Check cloudflared status
cloudflared --version
File System Issues
# Check available space
df -h
# Check loop device availability
sudo losetup -a
Debug Mode
For detailed debugging, you can modify the script to enable debug logging:
# In orb-registration.py, change:
logger = generate_logger(logging.INFO)
# To:
logger = generate_logger(logging.DEBUG)