Ship OpenFleet contracts and the OpenWall draft proposal (#177)

* feat: add OpenFleet membership and CoinPay rental contracts

* Propose OpenWall broadcasts and direct messaging contracts

* release: prepare OpenFleet and OpenWall public contracts

* fix: use tested npm for compatible CLI installs
This commit is contained in:
Anthony Ettinger 2026-09-13 00:57:45 -07:00 • committed by GitHub
parent a333726a1e
commit 45c7629953
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 2021 additions and 12 deletions

View file

@ -1,3 +1,9 @@
export { createOpenFleet } from "./openfleet.js";
export type {
OpenFleet, OpenFleetJsonValue, OpenFleetMember, OpenFleetMemberReference,
OpenFleetRental, OpenFleetRentalScope
} from "./openfleet.js";
export type LogicSrcId = string;
export interface LogicSrcTask {

View file

@ -0,0 +1,35 @@
import { describe, expect, it } from "vitest";
import { createOpenFleet, type OpenFleetMember } from "./index.js";
const members: OpenFleetMember[] = [
{ kind: "openagent", id: "analyst.coinpay", url: "https://example.com/agent.json" },
{ kind: "openswarm", id: `ed25519:${"a".repeat(64)}`, url: "https://example.com/manifest.json" }
];
describe("createOpenFleet", () => {
it.each([members.slice(0, 1), members.slice(1), members])("constructs single-kind and mixed fleets", (...fleetMembers) => {
const fleet = createOpenFleet({
id: "https://example.com/fleets/research", name: "Research", owner_did: "operator.coinpay",
members: fleetMembers
});
expect(fleet.type).toBe("logicsrc.openfleet");
expect(fleet.version).toBe("0.1");
expect(fleet.members).toEqual(fleetMembers);
expect(fleet.rentals).toBeUndefined();
});
it("keeps rental amounts as decimal strings and preserves metadata", () => {
const input: Parameters<typeof createOpenFleet>[0] = {
id: "https://example.com/fleets/research", name: "Research", owner_did: "operator.coinpay", members,
metadata: { support: { languages: ["en", "fr"] } },
rentals: [{
id: "hourly", scope: { kind: "fleet" },
rate: { amount: "9007199254740993.123456", currency: "USD", unit: "hour" },
payment: { provider: "coinpay", payee_did: "operator.coinpay", checkout_url: "https://example.com/rent" }
}]
};
const snapshot = structuredClone(input);
expect(createOpenFleet(input)).toEqual({ ...input, type: "logicsrc.openfleet", version: "0.1" });
expect(input).toEqual(snapshot);
});
});

View file

@ -0,0 +1,71 @@
export type OpenFleetJsonValue =
| null | boolean | number | string
| OpenFleetJsonValue[] | { [key: string]: OpenFleetJsonValue };
/** OpenAgent binds to a logicsrc.agent DID; OpenSwarm binds to a file key. */
export type OpenFleetMemberReference =
| { kind: "openagent"; id: string }
| { kind: "openswarm"; id: `ed25519:${string}` };
export type OpenFleetMember = OpenFleetMemberReference & {
/** HTTPS URL of the agent profile or the signed ipfile manifest. */
url: string;
name?: string;
role?: string;
metadata?: Record<string, OpenFleetJsonValue>;
};
export type OpenFleetRentalScope =
| { kind: "fleet" }
| { kind: "members"; members: OpenFleetMemberReference[] };
export interface OpenFleetRental {
id: string;
name?: string;
scope: OpenFleetRentalScope;
rate: {
/** Exact non-negative USD decimal string, with six fractional digits. */
amount: string;
currency: "USD";
/** Whole billing units; a month is 30 days, a task an agreed deliverable. */
unit: "hour" | "day" | "month" | "task";
};
minimum_units?: number;
maximum_units?: number;
valid_from?: string;
valid_until?: string;
terms_url?: string;
payment: {
provider: "coinpay";
payee_did: string;
/** Merchant-published HTTPS checkout entry point; no fixed CoinPay API. */
checkout_url: string;
};
metadata?: Record<string, OpenFleetJsonValue>;
}
export interface OpenFleet {
type: "logicsrc.openfleet";
version: "0.1";
/** Stable HTTPS fleet identifier, unique at its publisher's origin. */
id: string;
name: string;
owner_did: string;
description?: string;
updated_at?: string;
availability?: "available" | "busy" | "offline" | "unknown";
tags?: string[];
capabilities?: string[];
metadata?: Record<string, OpenFleetJsonValue>;
members: OpenFleetMember[];
rentals?: OpenFleetRental[];
}
/**
* Construct a descriptor without fetching members or initiating payments.
* Use validate("openfleet", document) from @logicsrc/validators before use:
* TypeScript alone cannot check DID/key formats or rental references.
*/
export function createOpenFleet(input: Omit<OpenFleet, "type" | "version">): OpenFleet {
return { ...input, type: "logicsrc.openfleet", version: "0.1" };
}