MINT: add a FORTH-79/83-standard-words-only lockdown personality

Captain Bob, 2026-09-07: "starting with that 00 user we created, we're
going to give access only to FORTH 79 and 83 standard words. everything
else is locked down."

New capsules/acl-std79.4th (blocks 4023-4047): walks a VM's own
dictionary (>LINK/LINK> traversal, same as ACL-INIT-PRIMITIVES/WORDS
already use) and permanently denies+pins every word not on an explicit
FORTH-79/83 allowlist, extracted from the real registered word set
(stack_words.c through control_words.c), not recited from memory.
Deliberately excludes, beyond plain non-standard words: BYE (100% ACL
bypass to the emergency console -- "needs more discussion, exclude for
now"), COLD/WARM/REBOOT/SAVE-SYSTEM (system lifecycle), the block/screen
editor L/S/SHOW/EDIT/UPDATE/SAVE-BUFFERS (lets a session rewrite
persistent block/capsule content, defeating the lockdown even though
nominally standard), BLK-ACL-*/BLK-OWNER@ (StarForth-specific), and
FORGET/FENCE (flagged as an unrestricted superpower word, 2026-09-03
audit). Keeps WORDS/VLIST/SEE (introspection only -- ACL is enforced
per-target-word at execution time regardless of how an XT was
obtained) and the parenthesized control-flow runtime primitives
((BRANCH) etc. -- IF/DO/LOOP compile calls to these; denying them
breaks ordinary control flow, not security).

MintPersonality enum (capsule_mint.h) lets capsule_mint_identity()
select which personality-source template gets written to a new
identity's devblock -- MINT_PERSONALITY_DEFAULT (unchanged) or
MINT_PERSONALITY_STD79_LOCKDOWN (EXECs acl-std79.4th then
ACL-LOCKDOWN-STD79 as the VM's own last bootstrap step). The actual
restriction logic stays entirely in FORTH per .claude/CLAUDE.md's
Word-Level ACL System rules ("ACL policy belongs in ACL.4th, never in
C") -- capsule_mint.c only picks which few-line bootstrap stub to
write. MINT's own stack signature gains a trailing restrict? flag;
capsule_zuse_boot.c's genesis mint (Zuse herself) explicitly passes
MINT_PERSONALITY_DEFAULT -- the superuser is never restricted.

Two real bugs found and fixed live during testing, both the same class
of self-referential fault: ACL-LOCKDOWN-STD79's own walk loop calls
ACL-STD79-ALLOWED?/ACL-STD79-LIST/ACL-ALLOW!/ACL-PIN on every single
iteration to do its job -- none of those are FORTH-79/83 standard
words, so the walk was denying its own load-bearing infrastructure
partway through and then faulting the next time it tried to call it
("VM fault -- emergency console disabled; halting", reproduced twice
live). Fixed by explicitly protecting all four in the allowlist
(block 4047) -- they must stay allowed for the walk to finish, not
because they belong on a "standard words" list.

Verified live end-to-end: minted a throwaway test identity with the
restrict? flag, confirmed her WIREBIND birth completes cleanly (no
faults, no shadow conflicts) on a single real attach, then USE'd into
her VM and confirmed standard arithmetic and user-defined words work
(1 2 + . -> 3; : X 5 5 * . ; X -> 25) while KILL is entirely unknown to
her dictionary and VM-EXEC is denied. One real, non-fatal side effect
found and left as-is (not asked to fix): the fleet's inter-VM messaging
pump (MSG-ARENA) is also denied by the lockdown, logging a harmless
per-idle-tick warning -- a fully locked-down VM doesn't participate in
message routing.

Not yet applied to the real identity 00 -- this commit is the
mechanism, verified against a disposable test identity only.

Three-arch clean qemu acceptance (single Zuse device, standard
regression case) passed on amd64, aarch64, and riscv64.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Ec88YKxxhZGG1RNnune78
This commit is contained in:
Robert Allan James
2026-09-07 15:41:56 -04:00
co-authored by Claude Sonnet 5
parent 8471d529bc
commit f4ded3e1a8
10 changed files with 27224 additions and 9 deletions
+28 -2
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-09-07T16:39:49Z -->
<!-- Generated by mkcapsule --manifest 2026-09-07T19:31:34Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. -->
@@ -9,6 +9,7 @@
| Capsule | Blocks claimed | xxHash64 | Signed |
|---------|----------------|----------|--------|
| `ACL.4th` | 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4015 | `0xd781d22148ff171d` | yes |
| `acl-std79.4th` | 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047 | `0x5a622e41d1fd0bb9` | yes |
| `artemis:init.4th` | 4110, 4111, 4112, 4113, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4177, 4178, 4179, 4180, 4181, 4182, 4851, 4852, 4853, 4854 | `0x1bb1886fc961c152` | yes |
| `block-acl.4th` | 4019, 4020 | `0xf6cc2a59e3a6734e` | yes |
| `common:messaging.4th` | 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040 | `0x9cb26fa2d67465db` | yes |
@@ -113,6 +114,31 @@
| 4020 | `block-acl.4th` | `0xf6cc2a59e3a6734e` | ok |
| 4021 | `zuse-eligibility.4th` | `0x8b49c1bc1e01dc58` | ok |
| 4022 | `zuse-eligibility.4th` | `0x8b49c1bc1e01dc58` | ok |
| 4023 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4024 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4025 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4026 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4027 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4028 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4029 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4030 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4031 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4032 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4033 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4034 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4035 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4036 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4037 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4038 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4039 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4040 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4041 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4042 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4043 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4044 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4045 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4046 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4047 | `acl-std79.4th` | `0x5a622e41d1fd0bb9` | ok |
| 4050 | `lib.4th` | `0x4b216635c359ef73` | ok |
| 4055 | `common:msg.4th` | `0x850a0382344ea6c4` | ok |
| 4060 | `doe-campaign.4th` | `0x3d4549142d91ec20` | ok |
@@ -361,4 +387,4 @@
None.
---
*34 capsule(s) scanned. Re-run `mkcapsule --manifest <dir>` to refresh.*
*35 capsule(s) scanned. Re-run `mkcapsule --manifest <dir>` to refresh.*
+179
View File
@@ -0,0 +1,179 @@
Block 4023
( acl-std79.4th - FORTH-79/83 standard-word-only lockdown )
( Denies+pins every dict word not on ACL-STD79-LIST below. )
( Excludes: BYE, COLD/WARM/REBOOT/SAVE-SYSTEM, the block )
( editor (L S SHOW EDIT UPDATE SAVE-BUFFERS), BLK-ACL-*, )
( FORGET/FENCE. Kept: (BRANCH) etc -- IF/DO/LOOP compile )
( calls to these; denying them breaks control flow. )
( Full rationale: FABRIC-3.md, 2026-09-07. )
CREATE ACL-STD79-LIST
Block 4024
( Stack + return stack )
' DROP , ' DUP , ' ?DUP , ' SWAP , ' OVER ,
' ROT , ' -ROT , ' DEPTH , ' PICK , ' ROLL ,
' >R , ' R> , ' R@ ,
Block 4025
( Memory )
' @ , ' ! , ' C@ , ' C! , ' +! , ' -! ,
' 2@ , ' 2! , ' FILL , ' MOVE , ' ERASE ,
' CELLS ,
Block 4026
( Arithmetic )
' + , ' - , ' * , ' / , ' MOD , ' /MOD ,
' */ , ' */MOD , ' 1+ , ' 1- , ' 2+ , ' 2- ,
' 2* , ' 2/ , ' ABS , ' NEGATE , ' MIN , ' MAX ,
Block 4027
( Logical / comparison, part 1 )
' AND , ' OR , ' XOR , ' NOT , ' INVERT ,
' LSHIFT , ' RSHIFT , ' 0= , ' 0< , ' 0> ,
' 0<> , ' = , ' <> ,
Block 4028
( Logical / comparison, part 2 )
' < , ' > , ' >= , ' <= , ' U< , ' U> ,
' WITHIN , ' TRUE , ' FALSE ,
Block 4029
( Mixed / double arithmetic, part 1 )
' M+ , ' M- , ' M* , ' M/MOD ,
' S>D , ' D+ , ' D- , ' DNEGATE , ' DABS ,
' DMAX , ' DMIN , ' D< , ' D= ,
Block 4030
( Mixed / double arithmetic, part 2 )
' 2DROP , ' 2DUP , ' 2SWAP , ' 2OVER ,
' 2ROT , ' 2>R , ' 2R> , ' 2R@ ,
' D0= , ' D0< , ' D2* , ' D2/ ,
Block 4031
( Formatted output )
' . , ' .R , ' U. , ' U.R , ' D. , ' D.R ,
' .S , ' ? , ' DUMP , ' <# , ' # , ' #S ,
' #> , ' HOLD , ' SIGN , ' BASE ,
' DECIMAL , ' HEX , ' OCTAL ,
Block 4032
( Strings, part 1 )
' COUNT , ' EXPECT , ' SPAN , ' QUERY ,
' TIB , ' WORD , ' (s") , ' S" , ' >IN ,
' SOURCE , ' BL , ' ['] ,
Block 4033
( Strings, part 2 )
' LITERAL , ' [LITERAL] , ' CONVERT ,
' NUMBER , ' ENCLOSE , ' -TRAILING ,
' CMOVE , ' CMOVE> , ' COMPARE ,
' SEARCH , ' SCAN , ' SKIP , ' BLANK ,
Block 4034
( I/O )
' EMIT , ' CR , ' KEY , ' ?TERMINAL ,
' TYPE , ' SPACE , ' SPACES ,
' (do-string) , ' ." ,
Block 4035
( Block -- read-only subset, no editor/writer )
' BLOCK , ' BUFFER , ' FLUSH , ' LOAD ,
' LIST , ' THRU , ' SCR , ' --> ,
Block 4036
( Dictionary space )
' HERE , ' ALIGN , ' ALLOT , ' , , ' C, ,
' 2, , ' PAD , ' SP! , ' SP@ , ' LATEST ,
Block 4037
( Dictionary internals -- introspection only; )
( execution stays gated per-target-word. )
' SMUDGE , ' HIDDEN , ' >BODY , ' >NAME ,
' NAME> , ' >LINK , ' LINK> , ' CFA ,
' LFA , ' NFA , ' PFA , ' TRAVERSE ,
' INTERPRET , ' FIND ,
Block 4038
( Vocabulary / search order )
' VOCABULARY , ' DEFINITIONS , ' CONTEXT ,
' CURRENT , ' FORTH , ' ORDER , ' (FIND) ,
Block 4039
( System -- lifecycle words excluded )
' WORDS , ' VLIST , ' SEE , ' PAGE ,
' EXECUTE , ' NOP , ' QUIT , ' ABORT ,
' (ABORT") , ' ABORT" , ' ( , ' \ ,
Block 4040
( Defining words -- FORGET/FENCE excluded )
' : , ' ; , ' CREATE , ' VARIABLE ,
' CONSTANT , ' IMMEDIATE , ' STATE ,
' [ , ' ] , ' COMPILE , ' [COMPILE] ,
' LIT , ' DOES> ,
Block 4041
( Control flow runtime primitives -- kept, )
( IF/DO/LOOP compile calls to these. )
' (BRANCH) , ' (0BRANCH) , ' (?DO) ,
' (DO) , ' (LOOP) , ' (+LOOP) , ' (LEAVE) ,
Block 4042
( Control flow, part 1 )
' IF , ' ELSE , ' THEN , ' BEGIN ,
' WHILE , ' REPEAT , ' AGAIN , ' UNTIL ,
Block 4043
( Control flow, part 2 )
' ?DO , ' DO , ' LOOP , ' +LOOP ,
' LEAVE , ' I , ' J , ' UNLOOP ,
' EXIT , ' CASE , ' OF , ' ENDOF ,
' ENDCASE ,
Block 4044
( ACL-STD79-ALLOWED? ( xt -- flag ) )
: ACL-STD79-ALLOWED? ( xt -- flag )
>R
ACL-STD79-LIST
BEGIN
DUP @
WHILE
DUP @ R@ = IF R> DROP DROP TRUE EXIT THEN
1 CELLS +
REPEAT
DROP R> DROP FALSE ;
Block 4047
( ACL-LOCKDOWN-STD79's own walk loop calls all )
( four of these on every iteration -- if the )
( walk denied any one, it would deny its own )
( ability to keep running: a real self- )
( referential fault caught live 2026-09-07 (VM )
( fault, emergency console disabled), twice, one )
( word at a time. Must all stay allowed. Sentinel )
( last. )
' ACL-STD79-LIST , ' ACL-STD79-ALLOWED? ,
' ACL-ALLOW! , ' ACL-PIN ,
0 , ( sentinel )
Block 4045
( ACL-WALK-MARK's own xt = correct walk- )
( start (the true dictionary head at the )
( moment the walk runs). Same >LINK/LINK> )
( traversal ACL-INIT-PRIMITIVES/WORDS use. )
: ACL-WALK-MARK ( -- ) ;
Block 4046
: ACL-LOCKDOWN-STD79 ( -- )
['] ACL-WALK-MARK
BEGIN
DUP
WHILE
DUP ACL-STD79-ALLOWED?
IF 1 OVER ACL-ALLOW!
ELSE 0 OVER ACL-ALLOW!
THEN
DUP ACL-PIN
DUP >LINK LINK>
SWAP DROP
REPEAT
DROP ;
BIN
View File
Binary file not shown.
+19 -1
View File
@@ -58,6 +58,20 @@ typedef enum {
* retry purposes. */
} MintResult;
/**
* MintPersonality - which personality-source template gets written to the
* new identity's devblock (identity_src_offset+1). Purely a template
* *selection* -- the actual restriction logic (the FORTH-79/83 allowlist,
* the walk-and-deny loop) lives entirely in capsules/acl-std79.4th, per
* the standing rule that ACL policy belongs in FORTH, never in C. This
* enum just picks which few-line bootstrap stub gets written; that stub
* is the only thing capsule_mint.c itself owns.
*/
typedef enum {
MINT_PERSONALITY_DEFAULT = 0, /* unrestricted -- today's only behavior until this enum existed */
MINT_PERSONALITY_STD79_LOCKDOWN = 1 /* EXECs acl-std79.4th then ACL-LOCKDOWN-STD79 as its last steps */
} MintPersonality;
/**
* capsule_mint_identity - Mint a fresh identity onto dev.
*
@@ -66,7 +80,8 @@ typedef enum {
* devblock 1 homeblocks_sig_t (HOMEBLOCKS_SIG_START_FBLOCK)
* devblock 2 DER cert, Zuse-signed (cert_offset)
* devblock 3 user_identity_seed_t (identity_src_offset)
* devblock 4 default personality source (identity_src_offset+1)
* devblock 4 personality source (selected by `personality`)
* (identity_src_offset+1)
*
* @param dev Already-open block device for the target drive.
* @param issuer_vm The signing identity -- in practice always Hera's own
@@ -92,6 +107,8 @@ typedef enum {
* install the cert into Hera's own VM immediately
* (vm_zuse_cert_install()) -- the seed otherwise only
* ever lives on the minted thumbdrive.
* @param personality Which personality-source template to write -- see
* MintPersonality's own doc comment above.
* @param drive_known_blank Pass 1 when the caller has *already* just run
* homeblocks_sig_check() on dev and confirmed
* HOMEBLOCKS_SIG_BLANK (e.g. capsule_zuse_boot_try_
@@ -113,6 +130,7 @@ MintResult capsule_mint_identity(struct blkio_dev *dev, VM *issuer_vm,
const char *full_name, const char *username,
const char *email, const char *phone,
uint8_t out_pubkey[32], uint8_t out_seed[32],
MintPersonality personality,
int drive_known_blank);
#endif /* __STARKERNEL__ */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+34 -3
View File
@@ -52,6 +52,28 @@ static const char MINT_DEFAULT_PERSONALITY[] =
": WELCOME ( -- ) .\" Minted identity -- default personality\" CR ;\n"
"WELCOME\n";
/* Restricted personality: FORTH-79/83 standard words only, everything else
* denied. The actual allowlist and the walk-and-deny logic live entirely in
* capsules/acl-std79.4th (ACL policy belongs in FORTH, never in C, per
* .claude/CLAUDE.md's Word-Level ACL System rules) -- this stub's only job
* is to EXEC that capsule and then call the one word it defines,
* ACL-LOCKDOWN-STD79, as this VM's own last bootstrap step. Block 4998:
* unused in the static capsule block-map (confirmed against
* capsules/BLOCK_MAP.md, 2026-09-07) -- 4999 is MINT_DEFAULT_PERSONALITY's
* own block above, same convention. EXEC itself is deliberately not on the
* std79 allowlist, so it's still usable here (nothing has been locked down
* yet at this point in the script) but becomes permanently denied the
* moment ACL-LOCKDOWN-STD79 finishes -- this is the one and only legitimate
* use of EXEC this VM will ever get. */
static const char MINT_RESTRICTED_PERSONALITY[] =
"Block 4998\n"
"S\" common:messaging.4th\" EXEC\n"
"MSG-CD-INIT\n"
"S\" acl-std79.4th\" EXEC\n"
"ACL-LOCKDOWN-STD79\n"
": WELCOME ( -- ) .\" Minted identity -- FORTH-79/83 standard words only\" CR ;\n"
"WELCOME\n";
/* Write exactly one devblock (4096 bytes) at devblock offset `devblock`,
* as 4 consecutive 1KiB forth-block writes -- same convention
* homeblocks_sig_check()'s own read loop already uses. */
@@ -145,6 +167,7 @@ MintResult capsule_mint_identity(struct blkio_dev *dev, VM *issuer_vm,
const char *full_name, const char *username,
const char *email, const char *phone,
uint8_t out_pubkey[32], uint8_t out_seed[32],
MintPersonality personality,
int drive_known_blank) {
if (!dev || !full_name || !username) return MINT_ERR_WRITE_FAIL;
@@ -231,11 +254,19 @@ MintResult capsule_mint_identity(struct blkio_dev *dev, VM *issuer_vm,
if (write_devblock(dev, MINT_IDENTITY_SRC_OFFSET, (const uint8_t *)&idrec) != 0)
return MINT_ERR_WRITE_FAIL;
/* Default personality source, in the devblock right after the seed
* record -- RUNCAP reads exactly this layout. */
/* Personality source, in the devblock right after the seed record --
* RUNCAP reads exactly this layout. Template selected by `personality`;
* see MintPersonality's own doc comment (capsule_mint.h) for why the
* actual restriction logic isn't here. */
const char *personality_src = (personality == MINT_PERSONALITY_STD79_LOCKDOWN)
? MINT_RESTRICTED_PERSONALITY
: MINT_DEFAULT_PERSONALITY;
size_t personality_len = (personality == MINT_PERSONALITY_STD79_LOCKDOWN)
? sizeof(MINT_RESTRICTED_PERSONALITY) - 1
: sizeof(MINT_DEFAULT_PERSONALITY) - 1;
uint8_t personality_block[4096];
memset(personality_block, 0, sizeof(personality_block));
memcpy(personality_block, MINT_DEFAULT_PERSONALITY, sizeof(MINT_DEFAULT_PERSONALITY) - 1);
memcpy(personality_block, personality_src, personality_len);
if (write_devblock(dev, MINT_IDENTITY_SRC_OFFSET + 1u, personality_block) != 0)
return MINT_ERR_WRITE_FAIL;
@@ -118,6 +118,7 @@ void capsule_zuse_boot_try_attach(struct blkio_dev *dev,
MintResult r = capsule_mint_identity(dev, (VM *)0, "Zuse", "zuse",
(const char *)0, (const char *)0,
pubkey, seed,
MINT_PERSONALITY_DEFAULT, /* Zuse is the superuser -- never restricted */
1 /* sig_rc already confirmed BLANK above */);
if (r != MINT_OK) {
console_println("Zuse: genesis mint failed");
+14 -3
View File
@@ -881,11 +881,16 @@ static int mint_pop_string(VM *vm, char *dst, size_t dst_cap)
}
/**
* @brief MINT ( fname-c fname-u uname-c uname-u email-c email-u phone-c phone-u -- ok? )
* @brief MINT ( fname-c fname-u uname-c uname-u email-c email-u phone-c phone-u restrict? -- ok? )
* Mint a fresh identity onto the currently attached USB drive, with a
* real human profile (FABRIC-2.md §F.20). full_name/username required
* and non-empty; pass a zero-length string (S" ") for email/phone to
* leave them null.
* leave them null. restrict? nonzero mints with the FORTH-79/83-only
* lockdown personality (MINT_PERSONALITY_STD79_LOCKDOWN,
* capsules/acl-std79.4th applies the actual restriction at that VM's own
* first birth) instead of the default, unrestricted one -- Captain Bob,
* 2026-09-07: "give access only to FORTH 79 and 83 standard words,
* everything else is locked down."
*/
static void mama_word_mint(VM *vm)
{
@@ -894,7 +899,9 @@ static void mama_word_mint(VM *vm)
char username[USER_IDENTITY_USERNAME_MAX];
char full_name[USER_IDENTITY_FULL_NAME_MAX];
/* Stack order: fname pushed first, phone last -- pop in reverse. */
/* Stack order: fname pushed first, restrict? last -- pop in reverse. */
if (vm->dsp < 0) { vm->error = 1; return; }
cell_t restrict_flag = vm_pop(vm);
if (mint_pop_string(vm, phone, sizeof(phone)) != 0) return;
if (mint_pop_string(vm, email, sizeof(email)) != 0) return;
if (mint_pop_string(vm, username, sizeof(username)) != 0) return;
@@ -907,8 +914,12 @@ static void mama_word_mint(VM *vm)
return;
}
MintPersonality personality = restrict_flag
? MINT_PERSONALITY_STD79_LOCKDOWN
: MINT_PERSONALITY_DEFAULT;
MintResult r = capsule_mint_identity(dev, vm, full_name, username, email, phone,
(uint8_t *)0, (uint8_t *)0,
personality,
0 /* not pre-checked -- keep the safety check */);
switch (r) {
case MINT_OK: