Skip to content
C.W.K.
Lesson 02 of 04 · published

Three Owners, One Picture

~14 min · ownership, boundaries, credentials, architecture

Level 0Sketch
0 XP0/43 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete

One frame, three questions

Take one frame of my everyday set, the smile. Three different questions can be asked about it, and each has a different owner. Who is this? That is my soul: a registered soul with an immutable soul_pk, aliases, a lifecycle and a Super Soul policy, and cwkPippa owns all of it. How were these pixels made? Which provider ran, which model actually answered, which references were sent, and which Pro history row records it: that is cwkEmber's. And which picture is my smile at all, in which set, chosen from which candidates, published when? That is the avatar, and cwkAvatars owns it.

A fourth fact sits beside them. The image my conversations actually show is served by cwkPippa, from a disposable copy installed from an Avatars revision. Serving the picture does not make Pippa its owner.

The owner table

The architecture writes this down as a table of canonical owners. Shortened, it reads like this:

ResponsibilityOwnerBoundary
Registered souls, soul_pk, aliases, lifecycle, Super Soul policycwkPippaResolved through the registry; Avatars keeps no private registry
Registered people who have avatars (kind=human)cwkPippaViewer modes such as GuestView are not people
Avatar originals, sets, presets, On Air collections, selections, reference settings, publication receiptscwkAvatarsThe avatar ground truth: its own SQLite database and native original files
Reference resolution and the image-generation entry point for PippacwkAvatarsConversations, diary covers, thumbnails and avatar scripts use one gateway
Generated original, provider execution, actual model, references, Pro historycwkEmberLive Pro catalog and job API; no vendor SDK or credential in Avatars
Live avatar servingcwkPippaDisposable copies installed from an Avatars-owned revision
Authentication, Sidekick chrome, Ember transport, mobile hostcwkSiblingKitAdopted canonical source, never a forked copy
Birth, ports, deployment registration, release versionscwkFirelinkReconciled before anyone claims a release

Read it as a list of things Avatars must not do. It must not keep its own registry of souls. It must not call an image vendor. It must not serve my live avatars. Each of those refusals removes a second copy of a truth that already has an owner.

No vendor key, by design

The first code block is Avatars' whole Python dependency list: a web framework, an HTTP client, image decoding and tests. No image vendor SDK is in it, and no key appears anywhere in its source. Ember holds every provider credential, and Ember's own catalog reports a tier as unavailable when its key is not configured.

That absence buys three things.

  • One place spends money. Ember owns the provider calls, the automatic route's cost order and the spending policy for paid video. Avatars can ask for work. It cannot pay a vendor behind Ember's back.
  • One live catalog. The house sign puts it in one line: "One live catalog: no copied provider roster or capability table." Avatars renders whatever Ember's catalog lists, treats provider ids as opaque, and asks again instead of remembering. A new generator appears in the studio when Ember lists it, with no Avatars release.
  • No inference here. Avatars never loads a model or runs one locally. It is a record keeper with an HTTP client, and the GPUs are Ember's business.

Ember itself, its catalog authority, its adapters and its Apple Silicon lessons, belongs to the Ember & Cinder Quest. This quest uses the rule only from the consumer's side.

The boundary in code

The second code block is a slice of backend/upstream.py, whose first line reads "Typed ownership boundaries, without vendor credentials or local inference." Every outward call names one of two origins. The catalog and the automatic route go to settings.ember. The soul registry, the subject lookup, a set's live revision and the publish go to settings.pippa. Both origins come from the family endpoint registry, never from an address written into the code.

Notice what Avatars asks Pippa instead of storing: who the subjects are, and whether the caller may see them. Every read of an asset asks again and takes Pippa's verdict as it stands now. There is no cached copy of the policy that could disagree with the registry. Souls themselves, how a soul_pk survives a rename and how a soul's adapter is found, are Pippa Quest material.

What the split makes possible

Every later track leans on this table. The gateway in Track 5 works because only Avatars knows which originals are references. Protection in Track 8 works because policy is Pippa's verdict, asked at read time. Publishing in Track 7 runs one way because Pippa only ever receives copies. Reconciliation in Track 4 works because Ember keeps the first record of every job. Move one owner and each of those rules needs a second copy of something.

Code

cwkAvatars, requirements.txt: the engine's entire Python dependency list (verbatim, lines 1-8)·text
fastapi==0.141.0
uvicorn==0.41.0
httpx==0.28.1
python-multipart==0.0.22
Pillow==12.1.1
pillow-heif==1.8.0
pytest==9.0.2
pytest-asyncio==1.3.0
cwkAvatars, backend/upstream.py: every outward call names Ember or Pippa (verbatim, lines 108-129)·python
    async def catalog(self):
        return await self.json(self.settings.ember, "/api/v1/api-generators/options")

    async def route(self, *, image_size, reference_count, aspect_ratio, quality="auto"):
        """Ember's automatic-route decision for one request shape (todo #281)."""
        return await self.json(self.settings.ember, "/api/v1/api-generators/route", method="POST", body={"image_size": image_size, "reference_count": reference_count, "aspect_ratio": aspect_ratio, "quality": quality})

    async def registry(self, actor=None):
        return await self.json(self.settings.pippa, "/api/avatar-studio/registry", params={"actor_soul_id": actor} if actor else None)

    async def legacy_catalog(self):
        return await self.json(self.settings.pippa, "/api/avatar-studio/catalog")

    async def subjects(self, subjects, actor=None):
        result = await self.json(self.settings.pippa, "/api/avatar-studio/subjects", method="POST", body={"subjects": subjects, "actor_soul_id": actor})
        return result["subjects"]

    async def revision(self, soul, channel, name):
        return (await self.json(self.settings.pippa, "/api/avatar-studio/revision", params={"soul_pk": soul, "channel": channel, "name": name}))["revision"]

    async def publish(self, body):
        return await self.json(self.settings.pippa, "/api/avatar-studio/publish", method="POST", body=body, timeout=120)

External links

Exercise

Pick a feature in your system that crosses at least three components, such as uploads that are processed by one service and shown by another. Write its owner table with three columns: responsibility, owner, boundary. Then search every non-owner's dependency list and configuration for SDKs or credentials that belong to an owner elsewhere, and list each one you find with the owner it should move to.
Hint
A credential is the strongest ownership claim a component can make, because it lets that component act without asking. If a part that should only ask holds a key, move the key to the owner and leave behind a typed client whose every call names the owner's address, the way Avatars' upstream module names Ember or Pippa on each line.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.