WHITEPAPER Technical Edition for Language Designers & Protocol Engineers 2025–2026 — Version 0.4.2 (IETF I-D: draft-ayerbe-trip-protocol-00)
ULISSY Foundation / GNS Protocol
ULissy is a domain-specific programming language designed for machines that move through physical space—mobile phones, vehicles, drones, wearables, and IoT devices. By treating identity, location, time, cryptography, and energy as first-class language primitives rather than library imports, ULissy enables developers to write secure, efficient, spatially-aware applications with compile-time safety guarantees.
ULissy transpiles to Rust and integrates natively with the GNS Protocol (Geospatial Naming System), providing a unified development experience from source code to deployed application across iOS, Android, desktop, and WebAssembly targets.
The name honors Ulysses (Odysseus)—the mythological figure who proved his identity not through credentials, but through his journey. In ULissy, as in the Odyssey, trajectory is identity.
| Component | Status | Description |
|---|---|---|
| Lexer | ✅ Complete | 68 token types, handles, facets, interpolation, search/nearby/ranked/by keywords |
| Parser | ✅ Complete | 20 statement types, full expression parsing, search expressions, if let binding |
| Type Checker | ✅ Complete | Domain-specific types, inference, validation, two-pass function resolution, privacy enforcement |
| Code Generator | ✅ Complete | Rust emission, Cargo.toml generation, typed search builder pattern |
| CLI | ✅ Complete | ulissy build, check, run, new, lex, parse, fmt, info |
| Runtime | ✅ Complete | gns-runtime crate with scheduling, sensors, location |
| Standard Library | ✅ Complete | 9 modules: core, spatial, crypto, temporal, sensors, trajectory, messaging, network, prelude |
| VS Code Extension | ✅ Complete | Syntax highlighting, 40+ snippets, commands, diagnostics |
Optional Binding:
if let statement — Optional binding syntax for safe unwrapping of Optional<T> values. Binds the unwrapped value as T in the then-block scope; the else-block executes when the value is nil. Completes ULissy’s optional story alongside ?. chaining and match/case nil.
let alice = search @alice // Optional<SearchResult>
if let peer = alice {
print(peer.handle) // peer is SearchResult (unwrapped)
} else {
print("Not found")
}
else if let chaining — ElseIfLet variant in ElseBranch enables chaining optional bindings in conditional chains.Unit Alias Expansion:
meter, kilometer, second, minute, hour, day) and abbreviations (m, km, sec, min, hr) alongside existing plural forms. All resolve to correct Distance or Duration types.
500.m // Distance (same as 500.meters)
5.km // Distance (same as 5.kilometers)
1.hour // Duration (same as 1.hours)
30.min // Duration (same as 30.minutes)
Type System Fixes:
Nil assignable to Optional<T> — is_assignable_from now correctly allows assigning nil to any optional type.
TrustScore comparable with Float — binary_result updated to allow trust score comparisons in search filter contexts (e.g., peer.trust > 0.5).
TrIP Search — Typed Filters & Full Query Coverage (Patch):
Expanded SearchTarget — Added Within { center, radius }, Identity { handle }, and Text { query } variants. Parser now handles search within(center, radius), search @handle, and search "text" in addition to search nearby.
Typed SearchFilter enum — Replaced generic { field, op, value } struct with semantic variants: TrustThreshold, FacetMatch, ActiveWithin, OrgMatch, FieldCompare. Compile-time validation for each filter type.
PresenceProof member access — SearchResult.proof now exposes epoch_count, spatial_diversity, trajectory_continuity, verification_level, and first_seen fields.
Optional<SearchResult> for identity lookups — search @handle returns Optional<SearchResult> instead of SearchResultSet, enabling if let unwrapping.
Ranking key expansion — Added Recency and Relevance (composite TrustRank) ranking keys alongside existing Trust and Distance. Parser accepts age as alias for recency.
Typed code generation — Codegen emits typed builder methods (.trust_min(), .facet(), .active_within(), .org(), .within(), .identity(), .text(), RankingKey::) instead of generic .filter() calls.
TrIP Search Primitives — Language-Level Spatial Discovery:
search keyword — New expression type for spatial-identity queries. Search is a first-class language construct, not a library call. Composes with let, for, every, when blocks.
nearby, ranked, by keywords — Added to lexer alongside existing within/where. search nearby(500.meters) where trust > 0.5 ranked by distance asc is a complete expression.
Search AST nodes — SearchExpr, SearchTarget, SearchFilter, SearchRanking with asc/desc ordering.
7 new types — TrustScore, SearchResult, SearchResultSet, PresenceProof, SearchQuery, SpatialFilter, IdentityFilter added to the type system.
Compile-time privacy enforcement — reject_private_in_search() gate blocks Breadcrumb, Trajectory, PrivateKey, Identity, and Array<private> from appearing in search contexts. If the code compiles, it respects the TrIP privacy model.
Builder-pattern code generation — Search expressions compile to gns_search::query() with chained .nearby(), .trust_min(), .rank_by() calls, emitting idiomatic Rust.
Parser Enhancements:
self keyword support — Added handling for SelfLower token so self can be used in expressions (e.g., in type invariants like signature.verify(self, owner))
Self keyword support — Added handling for SelfUpper token for type references
config keyword as expression — Added handling for Config token so config.fieldName works in expressions, enabling compile-time configuration access
default case in match statements — Added Default keyword to lexer and parser to support default: as a wildcard pattern in match statements
if expressions — Added parse_if_expression() so if can be used in expression context:
let x = if condition { a } else { b }
for statements — Added full ForStatement AST node and parse_for_statement() for iteration:
for item in collection {
process(item)
}
AssignmentExpr AST node and assignment parsing so variable reassignments work:
var counter = 0
counter = counter + 1
Lexer Enhancements:
Default keyword token — For match statement default/wildcard casesAST Enhancements:
ForStatement struct for for-in loopsAssignmentExpr struct for assignment expressionsForStatement variant to Statement enumAssignment variant to Expression enumType Checker Enhancements:
Developers building applications for moving machines face a fragmented landscape:
| Concern | Current Approach | Problems |
|---|---|---|
| Location | GPS libraries (CoreLocation, FusedLocation) | Platform-specific APIs, raw coordinates leak privacy |
| Identity | OAuth, JWT, platform accounts | Centralized, password-based, SIM-swappable |
| Cryptography | OpenSSL, libsodium bindings | Complex APIs, easy to misuse, silent failures |
| Time | Unix timestamps, Date libraries | No duration types, timezone bugs, no intervals |
| Energy | Platform battery APIs | Afterthought, not integrated into program logic |
| Connectivity | Reachability libraries | Boolean online/offline, no mesh or degraded states |
Developers must manually coordinate these concerns, leading to:
We have languages optimized for:
But no language treats physical space and movement as fundamental concepts.
ULissy fills this gap.
ULissy is built on five principles:
// trajectory.ul - Proof-of-Trajectory Collection
// Replaces ~250 lines of Rust with ~50 lines of ULissy
import ulissy.prelude
// Identity declaration - loads from secure keychain
identity me = Keychain.primary
// Module configuration - compile-time constants
config {
resolution: 7,
interval: 10.minutes,
minBreadcrumbsPerEpoch: 100
}
// Enum for location sources
enum LocationSource { gps, wifi, cell, ip, manual }
// Type with invariant (data integrity guarantee)
type Breadcrumb {
cell: H3Cell
timestamp: Moment
source: LocationSource
context: Hash
previousHash: Hash
signature: Signature
invariant timestamp <= now
invariant signature.verify(self, self.identity)
}
// Reactive computed property - auto-updates when dependencies change
computed status: CollectionStatus {
isActive: collection.running,
totalCount: me.trajectory.count,
pendingCount: me.trajectory.pending,
epochCount: me.trajectory.epochs.count,
progress: me.trajectory.pending / config.minBreadcrumbsPerEpoch
}
// Main collection loop
every config.interval when battery > 20 && gps.available {
let crumb = breadcrumb(
cell: here.h3(config.resolution),
timestamp: now,
source: .gps,
context: sensors.digest,
previous: me.trajectory.last?.hash ?? "genesis"
).signed(me)
me.trajectory.append(crumb)
}
// Epoch publishing trigger
when me.trajectory.pending >= config.minBreadcrumbsPerEpoch {
let epoch = me.trajectory.bundleEpoch()
network.publish(epoch)
}
This program:
status property that updates automaticallyThe equivalent in Swift + CoreLocation + CryptoKit would be 300+ lines with manual coordination between frameworks.
ULissy syntax follows these guidelines:
ULissy source files use the .ul extension:
identity.ul
trajectory.ul
messaging.ul
payments.ul
ULissy’s primitive types reflect the domain of moving machines:
| Type | Description | Size |
|---|---|---|
PublicKey |
Ed25519 public key | 32 bytes |
PrivateKey |
Ed25519 private key (enclave-bound) | 32 bytes |
Signature |
Ed25519 signature | 64 bytes |
Handle |
GNS @identifier | 1-20 chars |
SharedSecret |
X25519 ECDH output | 32 bytes |
| Type | Description | Details |
|---|---|---|
H3Cell |
Hexagonal grid cell | 64-bit identifier |
Resolution |
H3 precision level | 0-15 |
Distance |
Unit-aware length | meters, km, miles |
Heading |
Compass direction | 0-360 degrees |
Coordinates |
Lat/long pair | Internal only, not exposable |
| Type | Description | Examples |
|---|---|---|
Moment |
Instant in time | now, crumb.timestamp |
Duration |
Time span with units | 10.minutes, 2.hours |
Interval |
Recurring pattern | every 30.seconds |
| Type | Description | Algorithm |
|---|---|---|
Hash |
Digest value | SHA-256 |
Ciphertext |
Encrypted data | ChaCha20-Poly1305 |
Nonce |
Single-use value | 12 bytes |
| Type | Description | Values |
|---|---|---|
BatteryLevel |
Current charge | 0-100% |
PowerMode |
Energy profile | .low, .normal, .performance |
Primitives compose into protocol structures:
type Breadcrumb {
index: Uint64
timestamp: Moment
cell: H3Cell
context: Hash // WiFi + cell + IMU digest
previous: Hash // Chain link
signature: Signature // Ed25519 proof
invariant timestamp > previous.timestamp
invariant signature.valid(for: self, by: owner)
invariant cell.reachable(from: previous.cell, within: timestamp - previous.timestamp)
}
type Trajectory = Chain<Breadcrumb>
type Identity {
publicKey: PublicKey
privateKey: PrivateKey // Never leaves enclave
handle: Handle? // Optional until claimed
trajectory: Trajectory
computed trustScore: Float = trajectory.count / 100.0
}
type Envelope<T> {
sender: PublicKey
recipient: PublicKey
ephemeral: PublicKey // Forward secrecy
nonce: Nonce
ciphertext: Ciphertext // Encrypted T
signature: Signature
}
Types can have compile-time constraints:
// A handle requires proof of humanity
type Handle = String
where length in 1..20
where chars in [a-z, 0-9, _]
where owner.breadcrumbs >= 100
// Distance is unit-aware
type Distance = Number with Unit<Length>
let d1 = 500.meters
let d2 = 2.kilometers
let d3 = d1 + d2 // OK: 2500.meters
let t = 10.minutes
let x = d1 + t // COMPILE ERROR: cannot add Distance + Duration
Raw location data cannot be exposed without explicit quantization:
let raw = gps.current // Type: Coordinates (restricted)
print(raw) // COMPILE ERROR: Coordinates not printable
send(raw, to: server) // COMPILE ERROR: Coordinates not transmittable
let cell = raw.h3(resolution: 10) // Type: H3Cell (safe)
print(cell) // OK
send(cell, to: server) // OK
This enforces privacy at the language level.
// Identity declaration
identity me = Keychain.primary
identity work = Keychain.facet("microsoft")
// Variable declaration
let x = 42 // Immutable
var counter = 0 // Mutable
// Type annotation (optional, inferred)
let cell: H3Cell = here.h3(10)
// Constants
const BREADCRUMB_THRESHOLD = 100
const COLLECTION_INTERVAL = 10.minutes
// If statement
if battery > 20 {
collectBreadcrumb()
} else {
enterLowPowerMode()
}
// If expression (v0.3.1+)
let status = if connected { "online" } else { "offline" }
// Match statement with default (v0.3.1+)
match trustLevel {
case .anonymous: { denyAccess() }
case .verified: { allowBasic() }
case .trusted: { allowFull() }
default: { denyAccess() }
}
// For loops (v0.3.1+)
for breadcrumb in trajectory {
verify(breadcrumb)
}
for i in 0..10 {
print(i)
}
var counter = 0
counter = counter + 1 // Reassignment
var total = 0
for value in values {
total = total + value // Accumulator pattern
}
type Breadcrumb {
signature: Signature
owner: TIT
// 'self' refers to the current instance
invariant signature.verify(self, owner)
fn hash() -> Hash {
return sha256(self.bytes())
}
}
// 'Self' refers to the current type
impl Breadcrumb {
fn genesis() -> Self {
return Self { ... }
}
}
config {
resolution: 7,
minBreadcrumbs: 100
}
// Access config values in expressions
let cell = here.h3(config.resolution)
if count >= config.minBreadcrumbs {
publishEpoch()
}
GNS facets are first-class syntax:
// Protocol facets (hardcoded prefixes)
dix@me.post("Hello world", visibility: .public)
home@me/lights.set(brightness: 80%)
pay@merchant.request(50.USD)
email@alice.send(subject: "Meeting", body: message)
car@me.unlock()
// Organization facets (registered prefixes)
microsoft@me.authenticate()
stanford@researcher.verify()
// Periodic execution
every 10.minutes {
collectBreadcrumb()
}
// Conditional periodic
every 30.seconds when battery > 20 && connectivity.available {
sync()
}
// Delayed execution
after 5.seconds {
dismissNotification()
}
// Triggered execution
when me.trajectory.count >= 100 {
print("Ready to claim @handle!")
}
# Create new project
ulissy new my-app
# Compile
ulissy build
ulissy build --target ios
ulissy build --release
# Run
ulissy run
# Run specific file
ulissy run src/trip_tests.ul
# Check without compiling
ulissy check
# Format code
ulissy fmt
# Run tests
ulissy test
# Generate documentation
ulissy doc
# Package for distribution
ulissy package
# Debug: show tokens
ulissy lex src/main.ul
# Debug: show AST
ulissy parse src/main.ul
my-app/
├── ulissy.toml # Project configuration
├── src/
│ ├── main.ul # Entry point
│ ├── identity.ul
│ └── breadcrumbs.ul
├── tests/
│ └── integration.ul
├── assets/ # Icons, images
└── target/ # Build output
[package]
name = "my-app"
version = "0.1.0"
authors = ["Developer <dev@example.com>"]
[dependencies]
gns-crypto-core = "1.0"
gns-runtime = "1.0"
[targets]
default = ["ios", "android"]
[identity]
minimum-breadcrumbs = 100
h3-resolution = 10
collection-interval = "10m"
[build]
optimize = "size" # or "speed"
// Import everything
import ulissy.prelude
// Identity
identity me = Keychain.primary
identity work = Keychain.facet("company")
// Location
let cell = here.h3(7) // Current H3 cell
let dist = 500.meters // Distance
let nearby = neighbors(cell1, cell2) // Adjacency check
// Time
let timestamp = now // Current moment
let delay = 10.minutes // Duration
let future = now.plus(1.hours) // Arithmetic
// Crypto
let hash = sha256(data) // Hashing
let sig = me.sign(data) // Signing
let valid = sig.verify(data, key) // Verification
// Sensors
if battery > 20 { ... } // Battery level
if gps.available { ... } // GPS state
let digest = sensors.digest // Sensor context
// Trajectory
let crumb = breadcrumb(cell: cell).signed(me)
me.trajectory.append(crumb)
let epoch = me.trajectory.bundleEpoch()
// Network
network.publish(epoch)
network.sync()
let record = lookupHandle(@alice)
┌─────────────────────────────────────────────────────────────────┐
│ ULissy Compiler Pipeline │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Source (.ul) │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Lexer │ 64 token types │
│ │ │ Handles, facets, units │
│ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Parser │ 18 statement types │
│ │ │ Full expression support │
│ │ │ self/Self/config (v0.3.1) │
│ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Type Check │ Two-pass resolution (v0.3.1) │
│ │ │ Domain-specific types │
│ │ │ Constraint validation │
│ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Codegen │ Rust emission │
│ │ │ Cargo.toml generation │
│ └─────────────┘ │
│ │ │
│ ▼ │
│ Generated Rust → cargo build → Native Binary │
│ │
└─────────────────────────────────────────────────────────────────┘
The TrIP (Trajectory-based Recognition of Identity Proof) protocol, which defines the Proof-of-Trajectory mechanism implemented by ULissy’s trajectory module, has been formally submitted to the Internet Engineering Task Force (IETF) as an Individual Internet-Draft:
draft-ayerbe-trip-protocol-00 TrIP: Trajectory-based Recognition of Identity Proof February 2026 — Informational https://datatracker.ietf.org/doc/draft-ayerbe-trip-protocol/
The Internet-Draft specifies TrIP as a standalone, transport-agnostic protocol independent of ULissy, GNS, or any specific application layer. It defines:
The I-D references established IETF standards: Ed25519 (RFC 8032) for signatures, SHA-256 (RFC 6234) for hashing, and CBOR (RFC 8949) for serialization.
ULissy serves as the reference implementation language for TrIP. The ulissy.trajectory and ulissy.crypto standard library modules directly implement the data structures and algorithms specified in the Internet-Draft.
| Component | ULissy Module | I-D Section |
|---|---|---|
| Breadcrumb structure | ulissy.trajectory |
§3 Breadcrumb Specification |
| H3 spatial quantization | ulissy.spatial |
§3.3 Spatial Quantization |
| Context digest | ulissy.sensors |
§3.4 Context Digest Construction |
| Epoch bundling | ulissy.trajectory |
§5 Epoch Specification |
| Trust scoring | ulissy.trajectory |
§6 Trust Computation |
| Ed25519 signatures | ulissy.crypto |
§2 Protocol Architecture |
| CBOR encoding | ulissy.network |
§8 CBOR Encoding |
self and Self keyword supportconfig access in expressionsdefault case in match statementsif expressionsfor loopssearch expressions (4 targets: nearby, within, identity, text)if let optional bindingulissy command with 8 subcommands)gns-runtime)ulissy.core - Fundamental typesulissy.spatial - Location & H3ulissy.crypto - Cryptographyulissy.temporal - Time & durationulissy.sensors - Device sensorsulissy.trajectory - Proof-of-Trajectoryulissy.messaging - Encrypted messagingulissy.network - Network operationsulissy.prelude - All-in-one importdraft-ayerbe-trip-protocol-00 submitted and postedPriority: establish TrIP as an implementable, verifiable protocol standard.
trip-core Rust crate — Standalone reference implementation of the TrIP protocol (CBOR wire format, breadcrumb verification, epoch Merkle trees, TIT derivation) with zero ULissy dependency. Provides the second independent implementation required for IETF Standards Track advancement.gns-search Rust crate — Runtime implementation of the gns_search::query() builder pattern that compiled ULissy search expressions target. Bridges ULissy search primitives to the H3 spatial index via PostgreSQL with the H3 extension.ulissy doc command that extracts doc comments from .ul source files and emits structured Markdown or HTML documentation. Critical for protocol adoption visibility following IETF publication.Priority: make ULissy usable by developers beyond the core team.
ulissy add trip.epoch-verifier, ulissy add trip.trust-scorer). Positions packages as protocol components rather than generic code libraries.GET /v1/search) backed by the H3 spatial index, consuming GNS backend events. Client SDKs for JavaScript, Python, and Dart. See TrIP Search Whitepaper for full specification.Priority: production-grade language infrastructure.
.ul source.draft-ayerbe-trip-protocol from Informational to Standards Track with two verified independent implementations (ULissy reference + trip-core Rust crate) and working group adoption (target: RATS or new BOF session).ULissy represents a new category of programming language—one designed for the physical world rather than abstract computation. By treating space, time, identity, and movement as fundamental rather than incidental, ULissy makes secure, privacy-preserving, spatially-aware applications natural to write.
With the TrIP protocol now formally specified as IETF Internet-Draft draft-ayerbe-trip-protocol-00, the Proof-of-Trajectory mechanism has entered the international standards pipeline—the same process that produced TCP, HTTP, TLS, and DNS. ULissy provides the developer-facing implementation of this protocol.
Combined with the GNS Protocol and TrIP Search, ULissy provides the complete stack for identity-anchored computing:
The architecture spans from cryptographic proof to spatial discovery: TrIP proves you exist, GNS names you, TrIP Search makes you discoverable, and ULissy makes it all natural to build. The search layer — documented in the companion TrIP Search Whitepaper — completes the ecosystem by providing privacy-preserving discovery over the spatial-identity graph, where every result is ranked by cryptographic trust rather than advertising spend.
The era of moving machines requires a language that moves with them.
identity let var const fn config
type struct enum trait impl computed
if else match case guard invariant
for while in where when every
after within timeout budget send to
from as with return throw throws
async await import export public private
internal true false nil self Self
default search nearby ranked by
// Arithmetic
+ - * / %
// Comparison
== != < > <= >=
// Logical
&& || !
// Spatial
within near distance intersects
// Assignment
= += -= *= /=
// Optional
? ?? ?.
// Range
.. ..<
// Arrow
-> =>
// Numbers
42 // Int
3.14 // Float
0xFF // Hex
0b1010 // Binary
// Units
500.meters // Distance
2.kilometers // Distance
500.m // Distance (abbreviation)
5.km // Distance (abbreviation)
10.minutes // Duration
24.hours // Duration
1.hour // Duration (singular)
30.min // Duration (abbreviation)
80.percent
// Strings
"Hello"
"Hello, \(name)!" // Interpolation
// Collections
[1, 2, 3] // Array
{ x: 10, y: 20 } // Object literal
{ x: 10, y: 20 } as Point // Typed object
// Handles
@alice
@microsoft
// Facets
dix@alice
home@bob/lights
pay@merchant
| Statement | Syntax | Example |
|---|---|---|
| Identity | identity name = expr |
identity me = Keychain.primary |
| Let | let name = expr |
let cell = here.h3(7) |
| Var | var name = expr |
var counter = 0 |
| Const | const NAME = expr |
const MAX = 100 |
| Config | config { fields } |
config { resolution: 7 } |
| Function | fn name(params) -> Type { } |
fn add(a: Int, b: Int) -> Int { } |
| Type | type Name { fields } |
type Point { x: Int, y: Int } |
| Enum | enum Name { variants } |
enum Status { ok, error } |
| Computed | computed name: Type = expr |
computed total: Int = items.count |
| Every | every interval when cond { } |
every 10.minutes { } |
| When | when condition { } |
when count >= 100 { } |
| After | after delay { } |
after 5.seconds { } |
| Send | send to recipient { } |
send to @alice { msg: "hi" } |
| If | if cond { } else { } |
if x > 0 { } else { } |
| If Let | if let name = optional { } else { } |
if let peer = alice { print(peer.handle) } |
| Match | match expr { cases } |
match status { case ok: { } default: { } } |
| For | for item in collection { } |
for bc in trajectory { } |
| Search | let r = search target filters ranking |
let r = search nearby where trust > 0.5 ranked by distance |
| Return | return expr |
return result |
| Import | import path |
import ulissy.spatial |
Document Version: 0.4.2 Last Updated: February 2026 Authors: GNS Foundation License: MIT
Repository: https://github.com/GNS-Foundation/ULissy_Program
“The journey is the proof.” — ULissy Design Principle