Made Open

Resource Coordination

Resource coordination is the local sharing economy of Made Open — a decentralized system for matching needs, offers, and willing-to-dos between community members. It enables genuine peer-to-peer mutual aid without corporate intermediaries extracting value from the exchange.

Airbnb takes 15-20%. TaskRabbit takes 15-30%. Fiverr takes 20%. Resource coordination enables the same exchanges with 0% platform fee, because there is no platform. There is only federation.

The Problem with Platform Sharing Economies

Airbnb, Etsy, Fiverr, TaskRabbit, and Uber present themselves as sharing economies. They are not. They are corporations that:

  • Extract a percentage of every exchange
  • Control who can participate and under what terms
  • Own the reputation data and the relationships
  • Can revoke your access at any time
  • Profit from your labor and your social trust

The users do the work. The platform captures the margin.


The Three Declaration Types

Resource coordination begins with declarations — statements about what users have to offer or need.

Offer

"I have this and am willing to share or exchange it."

{
  "type": "Offer",
  "title": "React/TypeScript development — 10 hours",
  "description": "Senior engineer, 8 years experience. Happy to help with architecture or implementation.",
  "exchange_type": "reciprocal",    // skill-for-skill or time-banking
  "categories": ["software", "mentorship"],
  "location_preference": "remote",
  "expires_at": "2026-06-01"
}

Need

"I'm looking for this."

{
  "type": "Need",
  "title": "Help moving furniture — 3 hours",
  "description": "Moving from apartment to house, need 2-3 people for heavy lifting.",
  "exchange_type": "reciprocal",
  "categories": ["physical_labor"],
  "location": "San Francisco, CA",
  "timeframe": "next_two_weeks"
}

WillingToDo

"I'll do this in exchange for something."

{
  "type": "WillingToDo",
  "title": "Cook home-cooked meals for a family — weekly",
  "description": "Enjoy cooking, happy to prepare 3 dinners/week in exchange for childcare or language tutoring.",
  "exchange_type": "reciprocal",
  "categories": ["cooking", "domestic"]
}

Types of Exchange

TypeHow It WorksExample
ReciprocalSkill for skill, service for service"I'll fix your code; you teach me Spanish"
GiftNo return expected; free offering"I have extra tomatoes from the garden"
Time CreditCredits earned by giving time; spent when receiving (stored name: time_credit)1 hour helping anyone = 1 credit; spend 1 credit to receive 1 hour from anyone
MonetaryPay with currency via marketplace smart contractSkills listed at an hourly rate

The Matching Engine

There is no central matching server. Every hub runs its own local matching engine that compares declarations from across the federated network.

How Matching Works

User publishes a Need:
  "Help with furniture moving, San Francisco, next 2 weeks"
      │
      ▼
Hub broadcasts Need as ActivityPub Create(Need) to followers
      │
      ▼
Followers' hubs receive the Need
      │
      ▼
Each hub checks its local declaration index:
  "Do any of my user's Offers match this Need?"
  Criteria: categories, location proximity, availability, exchange type
      │
      ▼
Matches surfaced to the user whose Offer matched
  "Someone in your network needs furniture movers in your area"
      │
      ▼
User expresses interest → negotiation begins

Locality-First Matching

The matching engine prioritizes geographic proximity using location data from Android and Windows agents:

  • Location data in the Knowledge Graph maps to neighborhoods, cities, regions
  • Declarations can specify location preference: local / regional / remote
  • The engine ranks matches: same city > same region > remote
  • "Local first" honors the mutual aid principle: neighbors helping neighbors before reaching globally

Exchange Workflow

Once a match is found, the exchange workflow begins:

Need owner sees a match: Bob's Offer matches Sarah's Need
    │
    ▼
Sarah expresses interest via DIDComm message to Bob's hub
    │
    ▼
Negotiation (via DIDComm secure messaging)
  - Agree on scope, time, exchange terms
  - Either party can propose modifications
    │
    ▼
Agreement reached → exchange terms recorded
    │
    ├─► Reciprocal/Gift: Exchange happens (off-platform)
    │   Both parties confirm completion
    │
    └─► Monetary: Smart contract escrow initiated (optional)
        See marketplace.md for escrow flow
    │
    ▼
Exchange completed → both parties confirm
    │
    ▼
Reputation credentials issued:
  Bob → issues SkillProviderCredential to Sarah (if he received a service)
  Sarah → issues ReliableSharerCredential to Bob (if she received help)

No central server is required at any step. DIDComm handles secure messaging. ActivityPub broadcasts declarations. Reputation credentials are issued peer-to-peer.


Time Banking

Time banking is a credits-based exchange system where 1 hour of any service = 1 time bank credit, regardless of what the service is.

This radically levels the playing field: an hour of weeding the garden has the same value as an hour of legal advice. It prevents the replication of market hierarchies where highly-paid skills dominate.

Sarah gives 2 hours of Python tutoring → earns 2 credits
Sarah spends 2 credits → receives 2 hours of childcare from a neighbor

The neighbor who provided childcare now has 2 credits
They spend them on 2 hours of financial planning help

Credits circulate in the community; no money changes hands

Time Credit Ledger

The ledger is implemented as two tables defined in supabase/migrations/00006_phase6_governance.sql:

-- Per-user running balance + lifetime totals
time_credits (
  id              uuid          PRIMARY KEY DEFAULT gen_random_uuid(),
  owner_id        uuid          NOT NULL REFERENCES auth.users(id),
  balance         numeric(12,2) NOT NULL DEFAULT 0,   -- credits (1 credit ≈ 1 hour)
  lifetime_earned numeric(12,2) NOT NULL DEFAULT 0,
  lifetime_spent  numeric(12,2) NOT NULL DEFAULT 0,
  updated_at      timestamptz   DEFAULT now(),
  UNIQUE (owner_id)
)

-- Append-only ledger entries
time_credit_transactions (
  id             uuid          PRIMARY KEY DEFAULT gen_random_uuid(),
  owner_id       uuid          NOT NULL REFERENCES auth.users(id),
  amount         numeric(12,2) NOT NULL,     -- positive = credit, negative = debit
  balance_after  numeric(12,2) NOT NULL,
  tx_type        text          NOT NULL
                               CHECK (tx_type IN (
                                 'exchange_credit','exchange_debit',
                                 'governance_reward','dao_treasury_deposit',
                                 'dao_treasury_withdrawal','admin_adjustment'
                               )),
  reference_id   text,                       -- exchange_id, proposal_id, etc.
  note           text,
  created_at     timestamptz   DEFAULT now()
)

The ledger is scoped per user, not per community. Community-specific time banks are a future enhancement.


Federation

Declarations are published via ActivityPub so they propagate across the network:

// Create(Offer) ActivityPub activity
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Create",
  "actor": "https://alice.made-open.io/ap/actors/alice",
  "object": {
    "type": "Offer",
    "summary": "React/TypeScript development — 10 hours",
    "content": "Senior engineer, happy to help with architecture or implementation.",
    "tag": ["software", "mentorship"],
    "location": { "type": "Place", "name": "Remote" },
    "endTime": "2026-06-01T00:00:00Z"
  }
}

Discovery Modes

ModeHow
Follow networkAlice follows Bob; Alice's hub automatically checks Bob's declarations for matches
Community groupA community's ActivityPub actor aggregates all member declarations
Relay serversThird-party servers that aggregate declarations from many users; searchable index
Federated searchQuery the federated network for specific categories or locations

Privacy Controls

Users control who can see their declarations:

VisibilityWho Sees
publicEntire federated network
followersOnly users who follow them
communityOnly members of a specific community
privateOnly explicitly named DIDs

Some users may want broad visibility (to find matches quickly); others may prefer to keep their needs private (community-only or trusted network).


Data Model

Defined in supabase/migrations/00005_phase5_marketplace.sql:

declarations (
  id              uuid         PRIMARY KEY DEFAULT gen_random_uuid(),
  owner_id        uuid         NOT NULL REFERENCES auth.users(id),
  decl_type       text         NOT NULL
                               CHECK (decl_type IN ('offer','need','willing_to_do')),
  category        text         NOT NULL,   -- 'skill','goods','time','knowledge','service'
  title           text         NOT NULL,
  description     text,
  exchange_type   text         NOT NULL
                               CHECK (exchange_type IN ('reciprocal','gift','time_credit','monetary')),
  location_pref   text,                    -- 'local','regional','global'
  expires_at      timestamptz,
  status          text         NOT NULL DEFAULT 'active'
                               CHECK (status IN ('active','matched','expired','cancelled')),
  federated_ap_id text,                    -- ActivityPub id once broadcast
  created_at      timestamptz  DEFAULT now(),
  updated_at      timestamptz  DEFAULT now()
)

exchanges (
  id             uuid         PRIMARY KEY DEFAULT gen_random_uuid(),
  owner_id       uuid         NOT NULL REFERENCES auth.users(id),   -- initiator
  offer_decl_id  uuid         REFERENCES declarations(id),
  need_decl_id   uuid         REFERENCES declarations(id),
  offer_user_id  uuid         NOT NULL REFERENCES auth.users(id),
  need_user_id   uuid         NOT NULL REFERENCES auth.users(id),
  status         text         NOT NULL DEFAULT 'interest'
                              CHECK (status IN (
                                'interest','negotiating','agreed',
                                'exchanging','confirming','completed','cancelled'
                              )),
  exchange_type  text,
  notes          text,
  completed_at   timestamptz,
  created_at     timestamptz  DEFAULT now(),
  updated_at     timestamptz  DEFAULT now()
)

Note. The current schema uses a single category (text) column rather than a categories array, and does not yet include per-declaration visibility/community_id columns — visibility controls described above are aspirational.


How This "Hacks Capitalism"

The dominant platforms extract value from human cooperation:

  • TaskRabbit extracts margin from labor
  • Airbnb extracts margin from shelter sharing
  • Fiverr extracts margin from skills
  • Etsy extracts margin from crafts

Resource coordination removes the extraction point entirely:

Platform ModelResource Coordination
Central platform as intermediaryFederated peers negotiate directly
Platform controls reputationReputation lives in user's wallet as VCs
Platform can ban youCommunity governance decides, not a corporation
Platform takes 15-30%0% — there is no platform
Platform owns the relationshipYou own your connections; they're your federated follows
Platform monetizes your behaviorYour data stays in your hub

The same exchange that TaskRabbit facilitates at 20% overhead happens here at 0% overhead, with better reputation (portable VCs vs. platform-siloed ratings), and the relationship persists beyond any single transaction.


Capability Rollout

StageResource Coordination Capability
Federation foundationBasic declaration publishing via ActivityPub; followers see declarations
Full matchingMatching engine active; exchange workflow with DIDComm negotiation; SkillProviderCredential and ReliableSharerCredential issuance; community declaration aggregation
Advanced exchangesTime banking (credits ledger); smart contract integration for monetary exchanges; relay server protocol; geographic matching using location history