Repository: nats-io/nsc
Pull request #598 (2023-08-04 10:40:31)

[FIX] include account token position when describing exports
Addresses part of #597

When describing exports without any account token positions, the output looks like this:

```
+------------------------------------------------------------------------------------------------------------+
|                                                  Exports                                                   |
+--------------+-------------------+--------------+------------------------+--------+-------------+----------+
| Name         | Type              | Subject      | Account Token Position | Public | Revocations | Tracking |
+--------------+-------------------+--------------+------------------------+--------+-------------+----------+
| binary-cache | Service [Chunked] | nits.cache.> | -                      | No     | 0           | -        |
+--------------+-------------------+--------------+------------------------+--------+-------------+----------+
```

When describing exports that do contain account token positions, the output looks like this:

```
+----------------------------------------------------------------------------------------------------------------------------------+
|                                                             Exports                                                              |
+-----------------------------+------------------+----------------------+------------------------+--------+-------------+----------+
| Name                        | Type             | Subject              | Account Token Position | Public | Revocations | Tracking |
+-----------------------------+------------------+----------------------+------------------------+--------+-------------+----------+
| account-monitoring-streams  | Stream           | $SYS.ACCOUNT.*.>     | 3                      | Yes    | 0           | N/A      |
| account-monitoring-services | Service [Stream] | $SYS.REQ.ACCOUNT.*.* | 4                      | Yes    | 0           | -        |
+-----------------------------+------------------+----------------------+------------------------+--------+-------------+----------+
```


Patch:
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..29c1339
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: false
+contact_links:
+  - name: Discussion
+    url: https://github.com/nats-io/nsc/discussions
+    about: Ideal for ideas, feedback, or longer form questions.
+  - name: Chat
+    url: https://slack.nats.io
+    about: Ideal for short, one-off questions, general conversation, and meeting other NATS users!
diff --git a/.github/ISSUE_TEMPLATE/defect.yml b/.github/ISSUE_TEMPLATE/defect.yml
new file mode 100644
index 0000000..99b4800
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/defect.yml
@@ -0,0 +1,41 @@
+---
+name: Defect
+description: Report a defect, such as a bug or regression.
+labels:
+  - defect
+body:
+  - type: textarea
+    id: versions
+    attributes:
+      label: What version were you using?
+      description: Include the server version (`nats-server --version`) and any client versions when observing the issue.
+    validations:
+      required: true
+  - type: textarea
+    id: environment
+    attributes:
+      label: What environment was the server running in?
+      description: This pertains to the operating system, CPU architecture, and/or Docker image that was used.
+    validations:
+      required: true
+  - type: textarea
+    id: steps
+    attributes:
+      label: Is this defect reproducible?
+      description: Provide best-effort steps to showcase the defect.
+    validations:
+      required: true
+  - type: textarea
+    id: expected
+    attributes:
+      label: Given the capability you are leveraging, describe your expectation?
+      description: This may be the expected behavior or performance characteristics.
+    validations:
+      required: true
+  - type: textarea
+    id: actual
+    attributes:
+      label: Given the expectation, what is the defect you are observing?
+      description: This may be an unexpected behavior or regression in performance.
+    validations:
+      required: true
diff --git a/.github/ISSUE_TEMPLATE/proposal.yml b/.github/ISSUE_TEMPLATE/proposal.yml
new file mode 100644
index 0000000..d7da0ca
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/proposal.yml
@@ -0,0 +1,34 @@
+---
+name: Proposal
+description: Propose an enhancement or new feature.
+labels:
+  - proposal
+body:
+  - type: textarea
+    id: usecase
+    attributes:
+      label: What motivated this proposal?
+      description: Describe the use case justifying this request.
+    validations:
+      required: true
+  - type: textarea
+    id: change
+    attributes:
+      label: What is the proposed change?
+      description: This could be a behavior change, enhanced API, or a branch new feature.
+    validations:
+      required: true
+  - type: textarea
+    id: benefits
+    attributes:
+      label: Who benefits from this change?
+      description: Describe how this not only benefits you.
+    validations:
+      required: false
+  - type: textarea
+    id: alternates
+    attributes:
+      label: What alternatives have you evaluated?
+      description: This could be using existing features or relying on an external dependency.
+    validations:
+      required: false
diff --git a/cmd/describer.go b/cmd/describer.go
index 1fa8a50..177a5cb 100644
--- a/cmd/describer.go
+++ b/cmd/describer.go
@@ -18,6 +18,7 @@ package cmd
 import (
 	"bytes"
 	"fmt"
+	"strconv"
 	"strings"
 
 	"github.com/dustin/go-humanize"
@@ -237,7 +238,7 @@ func toYesNo(tf bool) string {
 func (e *ExportsDescriber) Describe() string {
 	table := tablewriter.CreateTable()
 	table.AddTitle("Exports")
-	table.AddHeaders("Name", "Type", "Subject", "Public", "Revocations", "Tracking")
+	table.AddHeaders("Name", "Type", "Subject", "Account Token Position", "Public", "Revocations", "Tracking")
 	for _, v := range e.Exports {
 		mon := "N/A"
 		rt := ""
@@ -257,7 +258,13 @@ func (e *ExportsDescriber) Describe() string {
 
 		st := TitleCase(v.Type.String())
 		k := fmt.Sprintf("%s%s", st, rt)
-		table.AddRow(v.Name, k, v.Subject, toYesNo(!v.TokenReq), len(v.Revocations), mon)
+
+		tp := "-"
+		if v.AccountTokenPosition > 0 {
+			tp = strconv.Itoa(int(v.AccountTokenPosition))
+		}
+
+		table.AddRow(v.Name, k, v.Subject, tp, toYesNo(!v.TokenReq), len(v.Revocations), mon)
 	}
 
 	tableDesc := tablewriter.CreateTable()
diff --git a/go.mod b/go.mod
index bfdbab9..d16b061 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
 	github.com/mitchellh/go-homedir v1.1.0
 	github.com/nats-io/cliprompts/v2 v2.0.0-20200221130455-2737f3b8cbb9
 	github.com/nats-io/jsm.go v0.0.35
-	github.com/nats-io/jwt/v2 v2.4.1
+	github.com/nats-io/jwt/v2 v2.5.0
 	github.com/nats-io/nats-server/v2 v2.9.6
 	github.com/nats-io/nats.go v1.24.0
 	github.com/nats-io/nkeys v0.4.4
diff --git a/go.sum b/go.sum
index f9b3418..1d22391 100644
--- a/go.sum
+++ b/go.sum
@@ -76,6 +76,8 @@ github.com/nats-io/jsm.go v0.0.35 h1:l03xuGttRA9b81Q0P/WEGm3e5DYof743ZEI4nQR3PUs
 github.com/nats-io/jsm.go v0.0.35/go.mod h1:AkNKZTxbvdFBOJCdlKuLHsRlOP+AI4hV9REQKmq3sWw=
 github.com/nats-io/jwt/v2 v2.4.1 h1:Y35W1dgbbz2SQUYDPCaclXcuqleVmpbRa7646Jf2EX4=
 github.com/nats-io/jwt/v2 v2.4.1/go.mod h1:24BeQtRwxRV8ruvC4CojXlx/WQ/VjuwlYiH+vu/+ibI=
+github.com/nats-io/jwt/v2 v2.5.0 h1:WQQ40AAlqqfx+f6ku+i0pOVm+ASirD4fUh+oQsiE9Ak=
+github.com/nats-io/jwt/v2 v2.5.0/go.mod h1:24BeQtRwxRV8ruvC4CojXlx/WQ/VjuwlYiH+vu/+ibI=
 github.com/nats-io/nats-server/v2 v2.9.6 h1:RTtK+rv/4CcliOuqGsy58g7MuWkBaWmF5TUNwuUo9Uw=
 github.com/nats-io/nats-server/v2 v2.9.6/go.mod h1:AB6hAnGZDlYfqb7CTAm66ZKMZy9DpfierY1/PbpvI2g=
 github.com/nats-io/nats.go v1.24.0 h1:CRiD8L5GOQu/DcfkmgBcTTIQORMwizF+rPk6T0RaHVQ=


Test patch:
diff --git a/cmd/addimport_test.go b/cmd/addimport_test.go
index b48467d..00ada43 100644
--- a/cmd/addimport_test.go
+++ b/cmd/addimport_test.go
@@ -32,7 +32,7 @@ func Test_AddImport(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, false)
 
 	ts.AddAccount(t, "B")
 
@@ -61,7 +61,7 @@ func Test_AddImportSelfImportsRejected(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, false)
 
 	token := ts.GenerateActivation(t, "A", "foobar.>", "A")
 	fp := filepath.Join(ts.Dir, "token.jwt")
@@ -77,7 +77,7 @@ func Test_AddImportFromURL(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, false)
 
 	ts.AddAccount(t, "B")
 
@@ -102,7 +102,7 @@ func Test_AddImportInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, false)
 
 	akp := ts.GetAccountKey(t, "A")
 	require.NotNil(t, akp)
@@ -135,7 +135,7 @@ func Test_AddImportGeneratingTokenInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, false)
 
 	akp := ts.GetAccountKey(t, "A")
 	require.NotNil(t, akp)
@@ -164,7 +164,7 @@ func Test_AddServiceImportGeneratingTokenInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "foobar.>", false)
+	ts.AddExport(t, "A", jwt.Service, "foobar.>", 0, false)
 
 	akp := ts.GetAccountKey(t, "A")
 	require.NotNil(t, akp)
@@ -194,7 +194,7 @@ func Test_AddPublicImport(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", true)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, true)
 	ts.AddAccount(t, "B")
 
 	_, _, err := ExecuteCmd(createAddImportCmd(), "--account", "B", "--src-account", "A", "--remote-subject", "foobar.>")
@@ -230,7 +230,7 @@ func Test_AddImport_PublicInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "foobar.>", true)
+	ts.AddExport(t, "A", jwt.Service, "foobar.>", 0, true)
 
 	akp := ts.GetAccountKey(t, "A")
 	require.NotNil(t, akp)
@@ -262,8 +262,8 @@ func Test_AddImport_PublicImportsInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", true)
-	ts.AddExport(t, "A", jwt.Service, "q.*", true)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, true)
+	ts.AddExport(t, "A", jwt.Service, "q.*", 0, true)
 
 	akp := ts.GetAccountKey(t, "A")
 	require.NotNil(t, akp)
@@ -311,7 +311,7 @@ func Test_AddImportWithSigningKeyToken(t *testing.T) {
 	ts.AddAccount(t, "A")
 	_, _, err := ExecuteCmd(createEditAccount(), "--sk", pk)
 	require.NoError(t, err)
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, false)
 
 	ts.AddAccount(t, "B")
 	token := ts.GenerateActivationWithSigner(t, "A", "foobar.>", "B", sk)
@@ -348,7 +348,7 @@ func Test_AddDecoratedToken(t *testing.T) {
 	ts.AddAccount(t, "A")
 	_, _, err := ExecuteCmd(createEditAccount(), "--sk", pk)
 	require.NoError(t, err)
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, false)
 
 	ts.AddAccount(t, "B")
 	token := ts.GenerateActivationWithSigner(t, "A", "foobar.>", "B", sk)
@@ -371,8 +371,8 @@ func Test_AddImport_LocalImportsInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", true)
-	ts.AddExport(t, "A", jwt.Service, "q", true)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, true)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, true)
 
 	akp := ts.GetAccountKey(t, "A")
 	require.NotNil(t, akp)
@@ -420,7 +420,7 @@ func Test_ImportStreamHandlesDecorations(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foobar.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foobar.>", 0, false)
 
 	ts.AddAccount(t, "B")
 	ac := ts.GenerateActivation(t, "A", "foobar.>", "B")
@@ -444,7 +444,7 @@ func Test_ImportServiceHandlesDecorations(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", false)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, false)
 
 	ts.AddAccount(t, "B")
 	ac := ts.GenerateActivation(t, "A", "q", "B")
@@ -486,10 +486,10 @@ func Test_AddWilcdardImport(t *testing.T) {
 
 	ts.AddAccount(t, "B")
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "priv-srvc.>", false)
-	ts.AddExport(t, "A", jwt.Stream, "priv-strm.>", false)
-	ts.AddExport(t, "A", jwt.Service, "pub-srvc.>", true)
-	ts.AddExport(t, "A", jwt.Stream, "pub-strm.>", true)
+	ts.AddExport(t, "A", jwt.Service, "priv-srvc.>", 0, false)
+	ts.AddExport(t, "A", jwt.Stream, "priv-strm.>", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "pub-srvc.>", 0, true)
+	ts.AddExport(t, "A", jwt.Stream, "pub-strm.>", 0, true)
 
 	aPub := ts.GetAccountPublicKey(t, "A")
 
@@ -523,9 +523,9 @@ func TestAddImport_SameName(t *testing.T) {
 
 	ts.AddAccount(t, "database")
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "stream.database", false)
+	ts.AddExport(t, "A", jwt.Stream, "stream.database", 0, false)
 	ts.AddAccount(t, "B")
-	ts.AddExport(t, "B", jwt.Stream, "stream.database", false)
+	ts.AddExport(t, "B", jwt.Stream, "stream.database", 0, false)
 
 	// account, locally available, name, local subj,
 	// database, true, A: -> stream.database, "stream.database", "ingest
diff --git a/cmd/deleteexport_test.go b/cmd/deleteexport_test.go
index 110c02b..ebb6f0f 100644
--- a/cmd/deleteexport_test.go
+++ b/cmd/deleteexport_test.go
@@ -26,9 +26,9 @@ func Test_DeleteExport(t *testing.T) {
 	ts := NewTestStore(t, "add_server")
 	defer ts.Done(t)
 
-	ts.AddExport(t, "A", jwt.Stream, "foo", true)
-	ts.AddExport(t, "A", jwt.Stream, "baz", true)
-	ts.AddExport(t, "B", jwt.Service, "bar", true)
+	ts.AddExport(t, "A", jwt.Stream, "foo", 0, true)
+	ts.AddExport(t, "A", jwt.Stream, "baz", 0, true)
+	ts.AddExport(t, "B", jwt.Service, "bar", 0, true)
 
 	tests := CmdTests{
 		{createDeleteExportCmd(), []string{"delete", "export", "--account", "A"}, nil, []string{"subject is required"}, true},
@@ -44,8 +44,8 @@ func Test_DeleteExportAccountRequired(t *testing.T) {
 	ts := NewTestStore(t, "add_server")
 	defer ts.Done(t)
 
-	ts.AddExport(t, "A", jwt.Stream, "foo", true)
-	ts.AddExport(t, "B", jwt.Service, "bar", true)
+	ts.AddExport(t, "A", jwt.Stream, "foo", 0, true)
+	ts.AddExport(t, "B", jwt.Service, "bar", 0, true)
 	GetConfig().SetAccount("")
 	_, _, err := ExecuteCmd(createDeleteExportCmd(), "--subject", "foo")
 	require.Error(t, err)
@@ -59,8 +59,8 @@ func Test_DeleteExportInteractiveManagedStore(t *testing.T) {
 	ts := NewTestStoreWithOperatorJWT(t, string(m["operator"]))
 	defer ts.Done(t)
 
-	ts.AddExport(t, "A", jwt.Stream, "foo", true)
-	ts.AddExport(t, "A", jwt.Stream, "baz", true)
+	ts.AddExport(t, "A", jwt.Stream, "foo", 0, true)
+	ts.AddExport(t, "A", jwt.Stream, "baz", 0, true)
 	ts.AddAccount(t, "B")
 
 	cmd := createDeleteExportCmd()
diff --git a/cmd/deleteimport_test.go b/cmd/deleteimport_test.go
index 6ff520d..9a967b5 100644
--- a/cmd/deleteimport_test.go
+++ b/cmd/deleteimport_test.go
@@ -27,8 +27,8 @@ func Test_DeleteImport(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo", false)
-	ts.AddExport(t, "A", jwt.Stream, "bar", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo", 0, false)
+	ts.AddExport(t, "A", jwt.Stream, "bar", 0, false)
 
 	ts.AddAccount(t, "B")
 	ts.AddImport(t, "A", "foo", "B")
@@ -49,7 +49,7 @@ func Test_DeleteImportAccountRequired(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo", 0, false)
 	ts.AddAccount(t, "B")
 	ts.AddImport(t, "A", "foo", "B")
 
@@ -64,8 +64,8 @@ func Test_DeleteImportInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo", false)
-	ts.AddExport(t, "A", jwt.Stream, "bar", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo", 0, false)
+	ts.AddExport(t, "A", jwt.Stream, "bar", 0, false)
 
 	ts.AddAccount(t, "B")
 	ts.AddImport(t, "A", "foo", "B")
diff --git a/cmd/describeaccount_test.go b/cmd/describeaccount_test.go
index 06ed07d..82a009d 100644
--- a/cmd/describeaccount_test.go
+++ b/cmd/describeaccount_test.go
@@ -152,7 +152,7 @@ func TestDescribeAccount_Latency(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", true)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, true)
 	ac, err := ts.Store.ReadAccountClaim("A")
 	require.NoError(t, err)
 	ac.Exports[0].Latency = &jwt.ServiceLatency{Sampling: 10, Results: "lat"}
@@ -247,7 +247,7 @@ func TestDescribeAccount_SubjectEncoding(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", true)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, true)
 
 	out, _, err := ExecuteCmd(rootCmd, "describe", "account", "--json")
 	require.NoError(t, err)
@@ -284,3 +284,24 @@ func TestDescribeAccount_Output(t *testing.T) {
 	require.NoError(t, err)
 	require.Contains(t, string(data), "-----BEGIN NATS ACCOUNT JWT-----\ney")
 }
+
+func TestDescribeAccount_Exports(t *testing.T) {
+	ts := NewTestStore(t, "O")
+	defer ts.Done(t)
+
+	ts.AddAccount(t, "A")
+	ts.AddExport(t, "A", jwt.Stream, "foo.bar.*.>", 0, true)
+
+	out, _, err := ExecuteCmd(rootCmd, "describe", "account")
+	require.NoError(t, err)
+	require.Contains(t, out, "| Account Token Position |")
+	require.Contains(t, out, "foo.bar.*.> | -")
+
+	ts.AddAccount(t, "B")
+	ts.AddExport(t, "B", jwt.Stream, "foo.bar.*.>", 3, true)
+
+	out, _, err = ExecuteCmd(rootCmd, "describe", "account", "-n", "B")
+	require.NoError(t, err)
+	require.Contains(t, out, "| Account Token Position |")
+	require.Contains(t, out, "foo.bar.*.> | 3")
+}
diff --git a/cmd/describejwt_test.go b/cmd/describejwt_test.go
index 9cd5abe..690e780 100644
--- a/cmd/describejwt_test.go
+++ b/cmd/describejwt_test.go
@@ -97,7 +97,7 @@ func TestDescribe_Activation(t *testing.T) {
 	ts.AddAccount(t, "A")
 	ts.AddAccount(t, "B")
 
-	ts.AddExport(t, "A", jwt.Stream, "AA.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "AA.>", 0, false)
 
 	token := ts.GenerateActivation(t, "A", "AA.>", "B")
 	tp := filepath.Join(ts.Dir, "token.jwt")
@@ -123,7 +123,7 @@ func TestDescribe_ActivationWithSigner(t *testing.T) {
 	ts.AddAccount(t, "B")
 
 	// generate an export, normally signed by the account
-	ts.AddExport(t, "A", jwt.Stream, "AA.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "AA.>", 0, false)
 	token := ts.GenerateActivation(t, "A", "AA.>", "B")
 	tp := filepath.Join(ts.Dir, "token.jwt")
 	require.NoError(t, Write(tp, []byte(token)))
diff --git a/cmd/editexport_test.go b/cmd/editexport_test.go
index c2306cb..493ae0a 100644
--- a/cmd/editexport_test.go
+++ b/cmd/editexport_test.go
@@ -28,7 +28,7 @@ func Test_EditExport_Private(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "a", true)
+	ts.AddExport(t, "A", jwt.Service, "a", 0, true)
 
 	_, _, err := ExecuteCmd(createEditExportCmd(), "--subject", "a", "--private", "--response-type", jwt.ResponseTypeChunked)
 	require.NoError(t, err)
@@ -43,7 +43,7 @@ func Test_EditExport_Latency(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "a", true)
+	ts.AddExport(t, "A", jwt.Service, "a", 0, true)
 
 	ac, err := ts.Store.ReadAccountClaim("A")
 	require.NoError(t, err)
@@ -65,8 +65,8 @@ func Test_EditExportInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "a", true)
-	ts.AddExport(t, "A", jwt.Service, "b", true)
+	ts.AddExport(t, "A", jwt.Service, "a", 0, true)
+	ts.AddExport(t, "A", jwt.Service, "b", 0, true)
 
 	link := "http://foo/bar"
 	_, _, err := ExecuteInteractiveCmd(createEditExportCmd(), []interface{}{1, 1, "c", "c", false, false, 1, "1s", "desc", link})
@@ -87,7 +87,7 @@ func Test_EditExportInteractiveLatency(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "a", true)
+	ts.AddExport(t, "A", jwt.Service, "a", 0, true)
 
 	_, _, err := ExecuteInteractiveCmd(createEditExportCmd(), []interface{}{0, 1, "c", "c", false, true, "header", "lat", 2, "", "", ""})
 	require.NoError(t, err)
@@ -107,7 +107,7 @@ func Test_EditExportRmLatencySampling(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "a", true)
+	ts.AddExport(t, "A", jwt.Service, "a", 0, true)
 
 	_, _, err := ExecuteCmd(createEditExportCmd(), "--subject", "a", "--sampling", "header", "--latency", "metrics.a")
 	require.NoError(t, err)
diff --git a/cmd/generateactivation_test.go b/cmd/generateactivation_test.go
index d277fc2..c4bce0f 100644
--- a/cmd/generateactivation_test.go
+++ b/cmd/generateactivation_test.go
@@ -30,7 +30,7 @@ func Test_GenerateActivation(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
 
 	_, pub, _ := CreateAccountKey(t)
 
@@ -47,8 +47,8 @@ func Test_GenerateActivationMultiple(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "A", jwt.Stream, "bar.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "A", jwt.Stream, "bar.>", 0, false)
 	ts.AddAccount(t, "B")
 
 	_, pub, _ := CreateAccountKey(t)
@@ -67,8 +67,8 @@ func Test_GenerateActivationMultipleAccountRequired(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "A", jwt.Stream, "bar.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "A", jwt.Stream, "bar.>", 0, false)
 	ts.AddAccount(t, "B")
 	GetConfig().SetAccount("")
 	_, _, err := ExecuteCmd(createGenerateActivationCmd())
@@ -91,7 +91,7 @@ func Test_GenerateActivationNoPrivateExports(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "foo", true)
+	ts.AddExport(t, "A", jwt.Service, "foo", 0, true)
 
 	_, _, err := ExecuteCmd(createGenerateActivationCmd())
 	require.Error(t, err)
@@ -103,7 +103,7 @@ func Test_GenerateActivationOutputsFile(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "foo", false)
+	ts.AddExport(t, "A", jwt.Service, "foo", 0, false)
 
 	_, pub, _ := CreateAccountKey(t)
 
@@ -118,7 +118,7 @@ func Test_GenerateActivationTargetAccountByName(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "foo", false)
+	ts.AddExport(t, "A", jwt.Service, "foo", 0, false)
 
 	ts.AddAccount(t, "B")
 
@@ -157,7 +157,7 @@ func Test_InteractiveGenerate(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "foo", false)
+	ts.AddExport(t, "A", jwt.Service, "foo", 0, false)
 
 	cmd := createGenerateActivationCmd()
 	HoistRootFlags(cmd)
@@ -177,7 +177,7 @@ func Test_InteractiveExternalKeyGenerate(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "foo", false)
+	ts.AddExport(t, "A", jwt.Service, "foo", 0, false)
 
 	cmd := createGenerateActivationCmd()
 	HoistRootFlags(cmd)
@@ -198,7 +198,7 @@ func Test_InteractiveMultipleAccountsGenerate(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "foo", false)
+	ts.AddExport(t, "A", jwt.Service, "foo", 0, false)
 	ts.AddAccount(t, "B")
 
 	cmd := createGenerateActivationCmd()
@@ -220,7 +220,7 @@ func Test_GenerateActivationUsingSigningKey(t *testing.T) {
 
 	ts.AddAccount(t, "A")
 	sk, pk, _ := CreateAccountKey(t)
-	ts.AddExport(t, "A", jwt.Stream, "foo", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo", 0, false)
 	_, _, err := ExecuteCmd(createEditAccount(), "--sk", pk)
 	require.NoError(t, err)
 
@@ -256,7 +256,7 @@ func Test_InteractiveGenerateActivationPush(t *testing.T) {
 	require.NoError(t, err)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", false)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, false)
 
 	_, apk, _ := CreateAccountKey(t)
 
diff --git a/cmd/importcollector_test.go b/cmd/importcollector_test.go
index cce838c..92f1789 100644
--- a/cmd/importcollector_test.go
+++ b/cmd/importcollector_test.go
@@ -27,8 +27,8 @@ func Test_ImportCollectorBasics(t *testing.T) {
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
 	ts.AddAccount(t, "A2")
-	ts.AddExport(t, "A2", jwt.Service, "foo", true)
-	ts.AddExport(t, "A2", jwt.Stream, "bar", false)
+	ts.AddExport(t, "A2", jwt.Service, "foo", 0, true)
+	ts.AddExport(t, "A2", jwt.Stream, "bar", 0, false)
 	ts.AddAccount(t, "A3")
 
 	exports, err := GetAllExports()
diff --git a/cmd/nkeyconfigbuilder_test.go b/cmd/nkeyconfigbuilder_test.go
index baea53e..ed9d1c8 100644
--- a/cmd/nkeyconfigbuilder_test.go
+++ b/cmd/nkeyconfigbuilder_test.go
@@ -76,8 +76,8 @@ func Test_NkeyResolverExportsStreamsServices(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "service.>", true)
-	ts.AddExport(t, "A", jwt.Stream, "stream.>", true)
+	ts.AddExport(t, "A", jwt.Service, "service.>", 0, true)
+	ts.AddExport(t, "A", jwt.Stream, "stream.>", 0, true)
 
 	builder := NewNKeyConfigBuilder()
 
@@ -102,8 +102,8 @@ func Test_NkeyResolverExportsPrivateStreamsServices(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "service.>", false)
-	ts.AddExport(t, "A", jwt.Stream, "stream.>", false)
+	ts.AddExport(t, "A", jwt.Service, "service.>", 0, false)
+	ts.AddExport(t, "A", jwt.Stream, "stream.>", 0, false)
 
 	builder := NewNKeyConfigBuilder()
 
@@ -128,8 +128,8 @@ func Test_NkeyResolverMapsImporter(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "service.b", false)
-	ts.AddExport(t, "A", jwt.Stream, "stream.a", false)
+	ts.AddExport(t, "A", jwt.Service, "service.b", 0, false)
+	ts.AddExport(t, "A", jwt.Stream, "stream.a", 0, false)
 
 	ts.AddAccount(t, "B")
 
diff --git a/cmd/revoke_clearactivation_test.go b/cmd/revoke_clearactivation_test.go
index 053e246..2edcb07 100644
--- a/cmd/revoke_clearactivation_test.go
+++ b/cmd/revoke_clearactivation_test.go
@@ -28,7 +28,7 @@ func TestClearRevokeActivation(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
 
 	_, pub, _ := CreateAccountKey(t)
 
@@ -59,11 +59,11 @@ func TestClearRevokeActivationInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "A", jwt.Service, "bar", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "bar", 0, false)
 	ts.AddAccount(t, "B")
-	ts.AddExport(t, "B", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "B", jwt.Service, "bar", false)
+	ts.AddExport(t, "B", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "B", jwt.Service, "bar", 0, false)
 
 	_, pub, _ := CreateAccountKey(t)
 
@@ -113,7 +113,7 @@ func TestClearRevokeActivationNoServiceExports(t *testing.T) {
 	ts := NewTestStore(t, "test")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
 	_, _, err := ExecuteCmd(createClearRevokeActivationCmd(), "--service")
 	require.Error(t, err)
 	require.Contains(t, err.Error(), "account \"A\" doesn't have service exports")
@@ -123,7 +123,7 @@ func TestClearRevokeActivationNoStreamExports(t *testing.T) {
 	ts := NewTestStore(t, "test")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", false)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, false)
 	_, _, err := ExecuteCmd(createClearRevokeActivationCmd())
 	require.Error(t, err)
 	require.Contains(t, err.Error(), "account \"A\" doesn't have stream exports")
@@ -133,7 +133,7 @@ func TestClearRevokeActivationServiceNoExports(t *testing.T) {
 	ts := NewTestStore(t, "test")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
 	_, _, err := ExecuteCmd(createClearRevokeActivationCmd(), "--service")
 	require.Error(t, err)
 	require.Contains(t, err.Error(), "account \"A\" doesn't have service exports")
@@ -143,7 +143,7 @@ func TestClearRevokeActivationInteractiveServiceNoRevocations(t *testing.T) {
 	ts := NewTestStore(t, "test")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", false)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, false)
 	input := []interface{}{true, 0}
 	_, _, err := ExecuteInteractiveCmd(createClearRevokeActivationCmd(), input)
 	require.Error(t, err)
@@ -154,7 +154,7 @@ func TestClearRevokeActivationInteractiveStreamNoRevocations(t *testing.T) {
 	ts := NewTestStore(t, "test")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "q", false)
+	ts.AddExport(t, "A", jwt.Stream, "q", 0, false)
 	input := []interface{}{false, 0}
 	_, _, err := ExecuteInteractiveCmd(createClearRevokeActivationCmd(), input)
 	require.Error(t, err)
@@ -165,7 +165,7 @@ func TestClearRevokeActivationDefault(t *testing.T) {
 	ts := NewTestStore(t, "test")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "s", false)
+	ts.AddExport(t, "A", jwt.Stream, "s", 0, false)
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "--target-account", "*")
 	require.NoError(t, err)
 	_, _, err = ExecuteCmd(createClearRevokeActivationCmd(), "--target-account", "*")
@@ -176,8 +176,8 @@ func TestClearRevokeActivationNotFound(t *testing.T) {
 	ts := NewTestStore(t, "test")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "s", false)
-	ts.AddExport(t, "A", jwt.Stream, "r", false)
+	ts.AddExport(t, "A", jwt.Stream, "s", 0, false)
+	ts.AddExport(t, "A", jwt.Stream, "r", 0, false)
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "--target-account", "*", "--subject", "s")
 	require.NoError(t, err)
 	_, _, err = ExecuteCmd(createRevokeActivationCmd(), "--target-account", "*", "--subject", "r")
@@ -191,8 +191,8 @@ func TestClearRevokeActivationSubjectRequired(t *testing.T) {
 	ts := NewTestStore(t, "test")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "s", false)
-	ts.AddExport(t, "A", jwt.Stream, "r", false)
+	ts.AddExport(t, "A", jwt.Stream, "s", 0, false)
+	ts.AddExport(t, "A", jwt.Stream, "r", 0, false)
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "--target-account", "*", "--subject", "s")
 	require.NoError(t, err)
 	_, _, err = ExecuteCmd(createClearRevokeActivationCmd(), "--target-account", "*")
diff --git a/cmd/revoke_listactivation_test.go b/cmd/revoke_listactivation_test.go
index 7599577..125b6ea 100644
--- a/cmd/revoke_listactivation_test.go
+++ b/cmd/revoke_listactivation_test.go
@@ -29,9 +29,9 @@ func TestRevokeListActivation(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "A", jwt.Service, "bar", false)
-	ts.AddExport(t, "A", jwt.Service, "public", true) // we support revoking public exports
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "bar", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "public", 0, true) // we support revoking public exports
 
 	_, pub, _ := CreateAccountKey(t)
 
@@ -95,7 +95,7 @@ func TestRevokeListActivationNoServiceExport(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "s", false)
+	ts.AddExport(t, "A", jwt.Stream, "s", 0, false)
 	_, _, err := ExecuteCmd(createRevokeListActivationCmd(), "--service")
 	require.Error(t, err)
 	require.Contains(t, err.Error(), "doesn't have service exports")
@@ -105,7 +105,7 @@ func TestRevokeListActivationNoStreamExport(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "s", false)
+	ts.AddExport(t, "A", jwt.Service, "s", 0, false)
 	_, _, err := ExecuteCmd(createRevokeListActivationCmd())
 	require.Error(t, err)
 	require.Contains(t, err.Error(), "doesn't have stream exports")
@@ -115,7 +115,7 @@ func TestRevokeListActivationDefaultExport(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "s", false)
+	ts.AddExport(t, "A", jwt.Service, "s", 0, false)
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "--service", "--target-account", "*")
 	require.NoError(t, err)
 	_, _, err = ExecuteCmd(createRevokeListActivationCmd(), "--service")
@@ -126,8 +126,8 @@ func TestRevokeListActivationNoDefaultExport(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "s", false)
-	ts.AddExport(t, "A", jwt.Service, "r", false)
+	ts.AddExport(t, "A", jwt.Service, "s", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "r", 0, false)
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "--service", "--target-account", "*", "--subject", "s")
 	require.NoError(t, err)
 	_, _, err = ExecuteCmd(createRevokeActivationCmd(), "--service", "--target-account", "*", "--subject", "r")
@@ -141,8 +141,8 @@ func TestRevokeListActivationExportNotFound(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "s", false)
-	ts.AddExport(t, "A", jwt.Service, "r", false)
+	ts.AddExport(t, "A", jwt.Service, "s", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "r", 0, false)
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "--service", "--target-account", "*", "--subject", "s")
 	require.NoError(t, err)
 	_, _, err = ExecuteCmd(createRevokeActivationCmd(), "--service", "--target-account", "*", "--subject", "r")
@@ -156,7 +156,7 @@ func TestRevokeListActivationHasNoRevocations(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "s", false)
+	ts.AddExport(t, "A", jwt.Service, "s", 0, false)
 	_, _, err := ExecuteCmd(createRevokeListActivationCmd(), "--service", "--subject", "s")
 	require.Error(t, err)
 	require.Contains(t, err.Error(), "service s has no revocations")
@@ -166,7 +166,7 @@ func TestRevokeListActivationInteractive(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "s", false)
+	ts.AddExport(t, "A", jwt.Service, "s", 0, false)
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "--service", "--subject", "s", "--target-account", "*")
 	require.NoError(t, err)
 	args := []interface{}{true, 0}
diff --git a/cmd/revokeactivation_test.go b/cmd/revokeactivation_test.go
index ba90805..1793494 100644
--- a/cmd/revokeactivation_test.go
+++ b/cmd/revokeactivation_test.go
@@ -28,9 +28,9 @@ func TestRevokeActivation(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "A", jwt.Service, "bar", false)
-	ts.AddExport(t, "A", jwt.Service, "public", true) // we support revoking public exports
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "bar", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "public", 0, true) // we support revoking public exports
 
 	_, pub, _ := CreateAccountKey(t)
 
@@ -57,8 +57,8 @@ func TestRevokeActivationAt(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "A", jwt.Service, "bar", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "bar", 0, false)
 
 	_, pub, _ := CreateAccountKey(t)
 
@@ -83,11 +83,11 @@ func TestRevokeActivationForStreamInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "A", jwt.Service, "bar", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "bar", 0, false)
 	ts.AddAccount(t, "B")
-	ts.AddExport(t, "B", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "B", jwt.Service, "bar", false)
+	ts.AddExport(t, "B", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "B", jwt.Service, "bar", 0, false)
 
 	_, pub, _ := CreateAccountKey(t)
 
@@ -123,11 +123,11 @@ func TestRevokeActivationForServiceInteractive(t *testing.T) {
 	defer ts.Done(t)
 
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "A", jwt.Service, "bar", false)
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "bar", 0, false)
 	ts.AddAccount(t, "B")
-	ts.AddExport(t, "B", jwt.Stream, "foo.>", false)
-	ts.AddExport(t, "B", jwt.Service, "bar", false)
+	ts.AddExport(t, "B", jwt.Stream, "foo.>", 0, false)
+	ts.AddExport(t, "B", jwt.Service, "bar", 0, false)
 
 	_, pub, _ := CreateAccountKey(t)
 
@@ -171,7 +171,7 @@ func TestRevokeActivationServiceNoExports(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", false)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, false)
 
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*")
 	require.Error(t, err)
@@ -182,7 +182,7 @@ func TestRevokeActivationStreamNoExports(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Stream, "q", false)
+	ts.AddExport(t, "A", jwt.Stream, "q", 0, false)
 
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*", "--service")
 	require.Error(t, err)
@@ -193,8 +193,8 @@ func TestRevokeActivationSubjectRequired(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", false)
-	ts.AddExport(t, "A", jwt.Service, "qq", false)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, false)
+	ts.AddExport(t, "A", jwt.Service, "qq", 0, false)
 
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*", "--service")
 	require.Error(t, err)
@@ -205,7 +205,7 @@ func TestRevokeActivationExportNotFound(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", false)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, false)
 
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*", "--service", "--subject", "foo")
 	require.Error(t, err)
@@ -216,7 +216,7 @@ func TestRevokeActivationDefaultSubject(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", false)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, false)
 
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*", "--service")
 	require.NoError(t, err)
@@ -226,7 +226,7 @@ func TestRevokeActivationAll(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", false)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, false)
 
 	_, _, err := ExecuteCmd(createRevokeActivationCmd(), "-t", "*", "--service", "--subject", "q")
 	require.NoError(t, err)
@@ -236,7 +236,7 @@ func TestRevokeActivationBadInteractiveAt(t *testing.T) {
 	ts := NewTestStore(t, "O")
 	defer ts.Done(t)
 	ts.AddAccount(t, "A")
-	ts.AddExport(t, "A", jwt.Service, "q", false)
+	ts.AddExport(t, "A", jwt.Service, "q", 0, false)
 
 	input := []interface{}{true, 0, "*", "hello"}
 	_, _, err := ExecuteInteractiveCmd(createRevokeActivationCmd(), input)
diff --git a/cmd/util_test.go b/cmd/util_test.go
index 156622d..1115591 100644
--- a/cmd/util_test.go
+++ b/cmd/util_test.go
@@ -26,6 +26,7 @@ import (
 	"os"
 	"path/filepath"
 	"regexp"
+	"strconv"
 	"strings"
 	"testing"
 	"time"
@@ -311,7 +312,7 @@ func (ts *TestStore) AddUserWithSigner(t *testing.T, accountName string, userNam
 	require.NoError(t, err)
 }
 
-func (ts *TestStore) AddExport(t *testing.T, accountName string, kind jwt.ExportType, subject string, public bool) {
+func (ts *TestStore) AddExport(t *testing.T, accountName string, kind jwt.ExportType, subject string, accountTokenPosition uint, public bool) {
 	flags := []string{"--account", accountName, "--subject", subject}
 	if !public {
 		flags = append(flags, "--private")
@@ -319,6 +320,9 @@ func (ts *TestStore) AddExport(t *testing.T, accountName string, kind jwt.Export
 	if kind == jwt.Service {
 		flags = append(flags, "--service")
 	}
+	if accountTokenPosition > 0 {
+		flags = append(flags, "--account-token-position", strconv.Itoa(int(accountTokenPosition)))
+	}
 
 	ts.AddAccount(t, accountName)
 	_, _, err := ExecuteCmd(createAddExportCmd(), flags...)