command

Grant Application Access

Asks CNA Auth to give a person access to an application, provisioning the account and user when they are new. Published by cna-one when an invited user is mirrored into a person; handled by cna-auth.

Command Topic: ApplicationKey: document

Overview

Intent to grant a person access to an application. It is a command: CNA AuthCNA AuthServicev1.0.0Authentication and identity provider for the CNA platform (accounts, tokens, OTP/2FA, per-application access grants). Co...SubscribesGrantApplicationAccess, RevokeApplicationAccess +2Ownercna-platformMapRepoView docs validates it and may reject it silently.

When it is published. CNA OneCNA OneServicev1.0.0Franchise operating system (franchises and employees, pricing, products and learning books, school operations). Publishe...PublishesGrantApplicationAccess, EmployeeCreated +6SubscribesInviteUser, FranchiseCreated +9Ownercna-platformMapRepoView docs publishes it from syncInviteUserToPerson, right after mirroring an InviteUser into a person and an employee. The access is requested on every invite, whether the person is new or already known, because provisioning the login is cna-auth’s job and this command is what tells it to. origin is the system the invite came from, read from the InviteUser envelope: today metadata.owner (hard-coded by the publishers to their own name, fallback ONE), metadata.producedBy once the envelope change lands.

What the consumer does. cna-auth (accountConsumer, handler grantApplicationAccess):

  1. Looks the application up by payload.application (applications.identifier). Unknown application: logged and dropped.
  2. Checks payload.origin against the application’s allowedOrigins (uppercase). Origin not allowed: logged and dropped. These two checks run before anything is written, so a rejected command leaves no account behind.
  3. Finds or creates the Account by document (with its OTP authentication method) and the User inside it, storing name, employeeId and id as the person id.
  4. Records the ApplicationGrant. The application only has to exist; isActive is a sign-in rule, so a grant on an inactive application becomes usable when it is turned back on.

Every failure is a log and a return. The consumer commits the offset either way, so there is no retry.

Kafka

Topic (aggregateRoot)Application
Message key (routingKey)payload.document
Contract ownerAUTH
metadata.eventGrantApplicationAccess
Consumer groupauth-user-events

Payload schema

Source of truth

export type ApplicationAccessPayload = {
id: string;
name: string;
email: string;
document: string;
employeeId: string;
application: string;
origin: string;
};
class GrantApplicationAccess extends Event<ApplicationAccessPayload> {
public static owner = "AUTH";
public static aggregateRoot = "Application";
public static routingKey = "document";
}

The copies in cna-auth and cna-one are identical.

Custom properties

PropertyValue
Contract Ownerx-contract-ownerAUTH
Kafka Topicx-kafka-topicApplication
Message Keyx-message-keydocument
Sourcex-sourcecna-auth api/app/events/auth/application/GrantApplicationAccess.ts
7 properties
idstring
required

Id of the person in the publishing application (cna-one Person.id). Stored on the account as its person id.

namestring
required

Full name of the person (name and surname joined).

emailstring
required

E-mail the login is provisioned on. Taken from the invite, not from what the publisher stores.

documentstring
required

Person document (CPF). Kafka message key and the field both systems correlate the person by.

employeeIdstring
required

CNA One employee id the access is keyed by. Stored on the account.

applicationstring
required

Identifier of the application in cna-auth (applications.identifier), e.g. cna-one.

originstring
required

System requesting the access: ONE, NEXUS or PLACEMENT. Must be one of the application's allowed origins; compared uppercase.