Files
logos-plugin-qt/cpp
Dario LipicarandClaude Opus 5 7cad5ec381 feat(consumer): logos::admitConsumer — one home for admitting a non-module (#27)
* feat(consumer): logos::admitConsumer — one home for admitting a non-module

Two hosts hand-rolled the same three steps independently — isolate an
identity, mint a credential, register it with capability_module — and the
duplication had already produced a bug: basecamp did the registration
inside the has-a-backend branch, below an early return, so pure-QML plugins
registered nothing. It survived only because those calls went out on the
host's ambient ring, where every token already existed and the handshake
was never reached. Remove the ambient ring (logos-protocol #71) and that
becomes a hard failure.

So the operation gets one home. admitConsumer isolates, mints, registers
and installs the credential as a single step, and hands back a
ConsumerIdentity. Both hosts lose their private copies: basecamp -16 net
lines, standalone-app -14.

It lives here rather than in logos-liblogos, which is where it was first
proposed. Both hand-rolled sites call LogosAPI, which is this repo's, and
the operation needs a capability_module client to register through — going
via liblogos's C API would add a hop for hosts already holding the Qt
object. logos-liblogos needs no change at all.

Named for what it does: a CONSUMER is admitted, not registered as a module.
It is never published to the registry, never callable, never in
--modules-dir.

Two guards, because the sharp edges here are silent ones:

  * adoptConsumerCredential REFUSES an isolated store. It exists for a
    co-process adopting its parent's credential into its own process ring,
    where the store IS that ring. Pointed at an in-process private store it
    would install whatever it was handed — including the host anchor —
    straight past adoptCredentialFor's refusal, putting the elevation #71
    removes one call away again.

  * A #error when logos-protocol is newer than the contract this file
    implements. The wave order is mandatory and was unenforced: bump the
    protocol alone and every isolated identity gets an empty store, while
    nothing fails to build (every MINOR guard in the fleet is >=) and the
    integration tests stay green (the ui-host half keeps working off its
    stdin credential). The bound fired on its first build — this change
    ships protocol 0.7 and it was set to 6 — and was proven non-inert by
    going red at 0.8.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(deps): relock logos-protocol onto master, which now carries #71

admitConsumer calls TokenManager::adoptCredentialFor and adoptCredential.
Both arrived with logos-protocol#71 ("a private store is created EMPTY"), so
the lock had to move past it — this branch still pinned 6c24fcb1, which is
0.6.0 and has neither:

  logos_consumer.cpp:89:  error: 'adoptCredentialFor' is not a member of 'TokenManager'
  logos_consumer.cpp:155: error: 'class TokenManager' has no member named 'adoptCredential'

Now b37a2e9f, protocol master with #71 merged.

This is the wave order the header documents, seen from the other side: the
empty-store change lands in protocol, and everything that makes it survivable
lands here. The guard in logos_consumer.h fires when this repo is BEHIND the
protocol; this commit is the ordinary case of catching up to it.

Verified on x86_64-linux with the relocked input:
  consumer-admission  PASS
  qt-host             PASS
  caller-contract     PASS
  glue-compiles       PASS

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 11:16:41 -03:00
..