# Current Case-Arm Discriminators
These five case-arms are critical to the base envelope specification.
```
case .node // [subject, assertion1...]
case .leaf // 24(CBOR)
case .wrapped // 200(envelope)
case .assertion // 201([predicate, object])
case .elided // bstr
```
These case-arms can be considered extensions to the base spec.
```
case .knownValue // 202(int|string)
case .encrypted // 205(encrypted)
case .compressed // 206(compressed)
```
# Analysis
* So far I've gotten rid of the need for the internal tag for elided, and for wrapped.
* Wrapped never had any use as a stand-alone tagged object, so good riddance. Downside: none.
* Elided (Digest) *does* have use as a stand-alone tagged object, but we can move it to the high 1+2 tag space, as it's only going to be used outside the context of envelope encoding. Downside: differenct encoding inside and outside envelope context.
* Known value is currently discriminated using a tag. But since it *only*be an int, we could say that ints are now *themselves* the discriminator for known value. This makes them even more compact as they won't even need a tag. Downside: different encoding inside and outside envelope context.
* Assertion also has no use outside the context of envelope encoding, so I'm thinking of changing it to a non-tag discriminator, like a single-entry map `{predicate: object}`. This only has 1-byte overhead to declare the map. Downside: none.
* I think we still need tags for `encrypted` and `compressed`. But I also think it wouldn't be bad to move them up to the high 1+2 space as well.
# Proposed New Format
These case-arms would be described in the next version of the I-D, but only one tag needs to be assigned: the master envelope tag (200).
```
case .node // [subject, assertion1...]
case .leaf // 24(CBOR)
case .wrapped // 200(envelope)
case .assertion // {predicate: object}
case .elided // bstr
```
This case does not need to be mentioned in the envelope I-D, but can be defined as an extension in another I-D. We can define its tag in the high 1+2 space, but now it doesn't need any tag at all inside an envelope.
```
case .knownValue // uint
```
These can be moved to high 1+2 tags that would meet no contest from IANA. They don't even need to be mentioned in the next version of the I-D, and could be defined in separate I-Ds.
```
case .encrypted // 205(encrypted)
case .compressed // 206(compressed)
```
These tags could be renumbered even higher, to the 1+4 first-come first-served range:
```
static let request = Tag(207, "request")
static let response = Tag(208, "response")
static let function = Tag(209, "function")
static let parameter = Tag(210, "parameter")
static let placeholder = Tag(211, "placeholder")
static let replacement = Tag(212, "replacement")
static let agreementPrivateKey = Tag(301, "agreement-private-key")
static let agreementPublicKey = Tag(302, "agreement-public-key")
static let commonIdentifier = Tag(312, "cid")
static let seedDigest = Tag(313, "seed-digest")
static let nonce = Tag(314, "nonce")
static let password = Tag(315, "password")
static let privateKeyBase = Tag(316, "crypto-prvkeys")
static let publicKeyBase = Tag(317, "crypto-pubkeys")
static let salt = Tag(318, "salt")
static let sealedMessage = Tag(319, "crypto-sealed")
static let signature = Tag(320, "signature")
static let signingPrivateKey = Tag(321, "signing-private-key")
static let signingPublicKey = Tag(322, "signing-public-key")
static let symmetricKey = Tag(323, "crypto-key")
```
The problem remains what to do about the CBOR tags that are in use but likely to be contested if we try to register them. We could
* do a hard fork, or
* adopt a transitional plan where we're accepting both these tags as legacy and a new higher tag, but only writing the new higher tag.
Obviously the hard fork is easier for us to implement. But either way, third-party developers currently using these tags may find themselves receiving constructs from us that no longer use them.
```
static let seed = Tag(300, "crypto-seed") // Fixed
static let ecKey = Tag(306, "crypto-eckey") // Fixed
static let sskrShare = Tag(309, "crypto-sskr") // Fixed
static let hdKey = Tag(303, "crypto-hdkey") // Fixed
static let derivationPath = Tag(304, "crypto-keypath") // Fixed
static let useInfo = Tag(305, "crypto-coin-info") // Fixed
static let address = Tag(307, "crypto-address") // Fixed
static let psbt = Tag(310, "crypto-psbt") // Fixed
static let account = Tag(311, "crypto-account") // Fixed
static let output = Tag(308, "crypto-output") // Fixed
static let outputScriptHash = Tag(400, "output-script-hash") // Fixed
static let outputWitnessScriptHash = Tag(401, "output-witness-script-hash") // Fixed
static let outputPublicKey = Tag(402, "output-public-key") // Fixed
static let outputPublicKeyHash = Tag(403, "output-public-key-hash") // Fixed
static let outputWitnessPublicKeyHash = Tag(404, "output-witness-public-key-hash") // Fixed
static let outputCombo = Tag(405, "output-combo") // Fixed
static let outputMultisig = Tag(406, "output-multisig") // Fixed
static let outputSortedMultisig = Tag(407, "output-sorted-multisig") // Fixed
static let outputRawScript = Tag(408, "output-raw-script") // Fixed
static let outputTaproot = Tag(409, "output-taproot") // Fixed
static let outputCosigner = Tag(410, "output-cosigner") // Fixed
static let outputDescriptorResponse = Tag(500, "output-descriptor-response") // Fixed
```