currentIdentity
Identity da sessão Registration que está executando o flow. Recebe o telefone quando a transferência termina.
Bullgate Access · documentação técnica
Contrato da fase 1 para o caso em que uma pessoa comprova um telefone durante o cadastro, mas esse telefone verificado já pertence a outra identity no mesmo realm.
Modelo mental
O conflito fica simples quando a integração não chama tudo de “conta”. A operação age sobre um identifier; as identities permanecem distintas.
currentIdentityIdentity da sessão Registration que está executando o flow. Recebe o telefone quando a transferência termina.
previousIdentityIdentity que já possui o telefone verificado. Mantém seu e-mail, credenciais, estado e referências existentes.
phone identifierÉ o único objeto transferido. O mesmo registro passa a apontar para a identity atual; não nasce uma cópia concorrente.
Pertence ao sistema integrador. O Bullgate não mistura dados, histórico ou cadastros locais das duas identities.
Quando o caso nasce
O código consulta o dono do telefone verificado depois que o OTP foi aprovado. Conhecer ou digitar um número não abre autoridade de resolução.
| Dono encontrado | Comportamento | Resultado |
|---|---|---|
| Nenhum | Cria o identifier verificado para a identity atual. | phoneVerified |
| A própria identity | Não existe conflito entre identities. | phoneVerified |
| Outra identity | Persiste PhonePossession, cria um IdentityResolutionCase e devolve o step de conflito. | resolvePhoneConflict |
phone-already-in-use. A resolução descrita nesta página não é aberta nesse caminho.
Fluxo executado
A UI envia requestPhoneVerification com o telefone em E.164.
A pessoa confirma o OTP. O sucesso registra a prova PhonePossession.
O Access encontra outra identity como dona verificada do mesmo identifier.
O flow devolve resolvePhoneConflict, dica mascarada e somente as ações permitidas.
transferPhoneToCurrentIdentity recebe o e-mail anterior e registra sucesso ou tentativa.
Prova, grant, transferência, sessão Product e conclusão são gravados em uma transação.
Entrada da interface
A interface não deduz possibilidades pelo nome da tela. Ela renderiza o step e oferece apenas os itens presentes em flow.actions.
Exemplo quando telefone é opcional
{
"protocolVersion": 1,
"flowId": "0199…",
"revision": 4,
"intent": "continueRegistration",
"status": "active",
"expiresAt": "2026-09-04T15:30:00Z",
"step": {
"type": "resolvePhoneConflict",
"previousEmailHint": "m***@empresa.com"
},
"actions": [
{ "id": "0199…", "type": "transferPhoneToCurrentIdentity" },
{ "id": "0199…", "type": "skipRegistration" }
]
}skipRegistration não aparece.expectedRevision. Qualquer snapshot mais novo invalida a ação antiga.Frontend e BFF
Com o SDK React Native, passe o snapshot recebido, o tipo oferecido e apenas o e-mail informado pela pessoa. O SDK mantém IDs e revisão do contrato.
React Native
if (flow.step?.type === "resolvePhoneConflict") {
const canTransfer = flow.actions.some(
action => action.type === "transferPhoneToCurrentIdentity",
);
if (canTransfer) {
current = await access.actOnFlow(
flow,
"transferPhoneToCurrentIdentity",
{ previousEmail },
);
}
}HTTP no BFF
POST /bullgate/access/v1/flows/{flowId}/actions
{
"requestId": "0199…",
"expectedRevision": 4,
"action": {
"id": "0199…",
"type": "transferPhoneToCurrentIdentity",
"input": { "previousEmail": "[email protected]" }
}
}action.id e action.type precisam ser copiados do mesmo item oferecido no snapshot. O e-mail é normalizado pelo Access antes da comparação.
Saída de sucesso
O envelope terminal traz o resultado do flow e uma sessão autenticada para a identity atual.
{
"flow": {
"status": "completed",
"step": null,
"actions": [],
"result": {
"type": "completed",
"outcome": "phoneTransferred",
"previousIdentityId": "0198…",
"currentIdentityId": "0199…"
}
},
"session": {
"state": "authenticated",
"identityId": "0199…",
"application": { "id": "…" }
}
}currentIdentityId.Resolved.Resposta recuperável e falha HTTP
| Código | Onde aparece | Resposta da integração |
|---|---|---|
phone-conflict-email-mismatch | flow.feedback | Marque previousEmail, mantenha o flow e permita nova tentativa se a ação continuar presente. |
phone-conflict-too-many-attempts | flow.feedback | A transferência desaparece. Se telefone for opcional, ainda pode existir skipRegistration. |
revision-conflict | HTTP 409 | Busque o snapshot atual com getFlow e renderize novamente. Não repita a ação antiga. |
action-not-available | HTTP 409 | A ação não pertence mais ao estado atual. Recarregue o flow. |
request-id-conflict | HTTP 409 | O mesmo requestId foi usado com payload diferente. Gere nova chave somente para uma nova intenção. |
flow-not-found | HTTP 404 | Capability ausente, inválida ou fora do escopo. Não tente reconstruí-la no cliente. |
session-inactive | HTTP 401 | A sessão Registration de origem não está mais ativa; reinicie pela autenticação. |
Regra implementada
A fase 1 usa uma regra fixa no fluxo. Ela ainda não expõe um objeto configurável de ResolutionPolicy.
PhonePossessionNasce da confirmação bem-sucedida do OTP enviado ao telefone em conflito e fica vinculada ao mesmo contexto de cadastro.
PreviousEmailKnowledgeNasce quando o e-mail normalizado informado coincide com o identifier da identity anterior. Não é um código enviado ao e-mail.
5. Tentativas de e-mail anterior são registradas individualmente.15. Neste caminho, o grant é criado e consumido dentro da mesma transação; não é entregue ao aplicativo.Máquina de estados persistida
No sucesso atual, as três últimas transições acontecem na mesma transação. Elas continuam explícitas para proteger invariantes e permitir evolução do modelo.
Rejected, Expired e Cancelled existem no enum, mas o fluxo de transferência da fase 1 não oferece comandos públicos específicos para conduzir o caso a esses estados.
Consistência
O Access não confia apenas no snapshot mostrado na tela. Antes do commit, confere novamente ownership, provas, tentativas, estado do caso e finalidade da sessão.
CollectingProofs e sem outcome escolhido.revision-conflict. A integração deve recarregar o snapshot; nunca forçar o resultado antigo.
Comportamento da aplicação
step.type.flow.actions.skipRegistration não foi oferecida.Contrato honesto
O SDK e o domínio já reservam nomes para uma resolução mais ampla. Integrações da fase 1 devem ignorá-los até que apareçam no array de ações de um snapshot real.
recoverPreviousIdentity.ConsolidateProvisionalIdentity.flow.actions naquela revisão.
Prévia: nenhuma mensagem é enviada por este campo.