@truealter/sdk 0.2.0 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -49
- package/dist/bin/alter-identity.js +53 -39
- package/dist/bin/mcp-bridge.js +1 -3
- package/dist/index.cjs +66 -86
- package/dist/index.d.cts +67 -197
- package/dist/index.d.ts +67 -197
- package/dist/index.js +66 -86
- package/package.json +10 -5
- package/dist/bin/alter-identity.js.map +0 -1
- package/dist/bin/mcp-bridge.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -306,7 +306,7 @@ function parsePaymentHeader(header) {
|
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
// src/mcp.ts
|
|
309
|
-
var MCP_PROTOCOL_VERSION = "2025-
|
|
309
|
+
var MCP_PROTOCOL_VERSION = "2025-11-25";
|
|
310
310
|
var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 502, 503, 504]);
|
|
311
311
|
var MCPClient = class {
|
|
312
312
|
endpoint;
|
|
@@ -603,6 +603,8 @@ function base64urlDecode(input) {
|
|
|
603
603
|
// src/provenance.ts
|
|
604
604
|
var _jwksCache = /* @__PURE__ */ new Map();
|
|
605
605
|
var JWKS_TTL_MS = 5 * 60 * 1e3;
|
|
606
|
+
var JWKS_MAX_BYTES = 64 * 1024;
|
|
607
|
+
var JWKS_CACHE_MAX_ENTRIES = 32;
|
|
606
608
|
var DEFAULT_VERIFY_AT_ALLOWLIST = Object.freeze([
|
|
607
609
|
"api.truealter.com",
|
|
608
610
|
"mcp.truealter.com"
|
|
@@ -712,7 +714,8 @@ async function fetchPublicKeys(jwksUrl, fetchImpl = fetch) {
|
|
|
712
714
|
return fetchJwks(jwksUrl, fetchImpl);
|
|
713
715
|
}
|
|
714
716
|
async function fetchJwks(url, fetchImpl) {
|
|
715
|
-
const
|
|
717
|
+
const cacheKey = jwksCacheKey(url);
|
|
718
|
+
const cached = _jwksCache.get(cacheKey);
|
|
716
719
|
if (cached && Date.now() - cached.fetched < JWKS_TTL_MS) return cached.jwks;
|
|
717
720
|
let resp;
|
|
718
721
|
try {
|
|
@@ -729,13 +732,45 @@ async function fetchJwks(url, fetchImpl) {
|
|
|
729
732
|
);
|
|
730
733
|
}
|
|
731
734
|
if (!resp.ok) throw new AlterNetworkError(`${url} \u2192 HTTP ${resp.status}`);
|
|
732
|
-
const
|
|
735
|
+
const contentLength = resp.headers.get("content-length");
|
|
736
|
+
if (contentLength !== null) {
|
|
737
|
+
const n = Number.parseInt(contentLength, 10);
|
|
738
|
+
if (Number.isFinite(n) && n > JWKS_MAX_BYTES) {
|
|
739
|
+
throw new AlterProvenanceError(
|
|
740
|
+
`${url} \u2192 JWKS too large: ${n} > ${JWKS_MAX_BYTES} bytes`
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
const body = await resp.text();
|
|
745
|
+
if (body.length > JWKS_MAX_BYTES) {
|
|
746
|
+
throw new AlterProvenanceError(
|
|
747
|
+
`${url} \u2192 JWKS too large: ${body.length} > ${JWKS_MAX_BYTES} bytes`
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
let doc;
|
|
751
|
+
try {
|
|
752
|
+
doc = JSON.parse(body);
|
|
753
|
+
} catch (err) {
|
|
754
|
+
throw new AlterProvenanceError(`invalid JWKS at ${url}: ${err.message}`);
|
|
755
|
+
}
|
|
733
756
|
if (!doc || !Array.isArray(doc.keys)) {
|
|
734
757
|
throw new AlterProvenanceError(`invalid JWKS at ${url}`);
|
|
735
758
|
}
|
|
736
|
-
_jwksCache.
|
|
759
|
+
if (_jwksCache.size >= JWKS_CACHE_MAX_ENTRIES && !_jwksCache.has(cacheKey)) {
|
|
760
|
+
const oldest = _jwksCache.keys().next().value;
|
|
761
|
+
if (oldest !== void 0) _jwksCache.delete(oldest);
|
|
762
|
+
}
|
|
763
|
+
_jwksCache.set(cacheKey, { fetched: Date.now(), jwks: doc });
|
|
737
764
|
return doc;
|
|
738
765
|
}
|
|
766
|
+
function jwksCacheKey(url) {
|
|
767
|
+
try {
|
|
768
|
+
const parsed = new URL(url);
|
|
769
|
+
return `${parsed.origin}${parsed.pathname}`;
|
|
770
|
+
} catch {
|
|
771
|
+
return url;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
739
774
|
function resolveVerifyAt(verifyAt, allowlist = DEFAULT_VERIFY_AT_ALLOWLIST) {
|
|
740
775
|
if (typeof verifyAt !== "string" || verifyAt.length === 0) {
|
|
741
776
|
throw new Error("verify_at must be a non-empty string");
|
|
@@ -758,6 +793,9 @@ function resolveVerifyAt(verifyAt, allowlist = DEFAULT_VERIFY_AT_ALLOWLIST) {
|
|
|
758
793
|
if (parsed.protocol !== "https:") {
|
|
759
794
|
throw new Error(`verify_at must be https: ${verifyAt}`);
|
|
760
795
|
}
|
|
796
|
+
if (parsed.username || parsed.password) {
|
|
797
|
+
throw new Error(`verify_at must not contain userinfo: ${verifyAt}`);
|
|
798
|
+
}
|
|
761
799
|
const host = parsed.hostname.toLowerCase();
|
|
762
800
|
const allowed = allowlist.some((h) => h.toLowerCase() === host);
|
|
763
801
|
if (!allowed) {
|
|
@@ -838,7 +876,16 @@ var AlterClient = class {
|
|
|
838
876
|
await this.mcp.initialize();
|
|
839
877
|
}
|
|
840
878
|
// ── Free tier ────────────────────────────────────────────────────────
|
|
841
|
-
/**
|
|
879
|
+
/** First handshake — confirms the connection, returns trust tier and tool counts. */
|
|
880
|
+
async helloAgent() {
|
|
881
|
+
return this.mcp.callTool("hello_agent", {});
|
|
882
|
+
}
|
|
883
|
+
/** Resolve a ~handle (e.g. ~drew) to its canonical form and kind. No auth required. */
|
|
884
|
+
async resolveHandle(args) {
|
|
885
|
+
const payload = typeof args === "string" ? { query: args } : args;
|
|
886
|
+
return this.mcp.callTool("alter_resolve_handle", payload);
|
|
887
|
+
}
|
|
888
|
+
/** Verify a person is registered with ALTER (handle or id). */
|
|
842
889
|
async verify(handleOrId, claims) {
|
|
843
890
|
const args = handleOrId.includes("@") ? { candidate_id: "", email: handleOrId } : handleOrId.startsWith("~") ? (
|
|
844
891
|
// ~handle — server resolves these via the candidate_id field
|
|
@@ -874,12 +921,6 @@ var AlterClient = class {
|
|
|
874
921
|
async getCompetencies(args) {
|
|
875
922
|
return this.mcp.callTool("get_competencies", args);
|
|
876
923
|
}
|
|
877
|
-
async createIdentityStub(args) {
|
|
878
|
-
return this.mcp.callTool("create_identity_stub", args);
|
|
879
|
-
}
|
|
880
|
-
async submitContext(args) {
|
|
881
|
-
return this.mcp.callTool("submit_context", args);
|
|
882
|
-
}
|
|
883
924
|
async searchIdentities(args) {
|
|
884
925
|
return this.mcp.callTool("search_identities", args);
|
|
885
926
|
}
|
|
@@ -904,9 +945,6 @@ var AlterClient = class {
|
|
|
904
945
|
async getPrivacyBudget(args) {
|
|
905
946
|
return this.mcp.callTool("get_privacy_budget", args);
|
|
906
947
|
}
|
|
907
|
-
async disputeAttestation(args) {
|
|
908
|
-
return this.mcp.callTool("dispute_attestation", args);
|
|
909
|
-
}
|
|
910
948
|
// ── Golden Thread ────────────────────────────────────────────────────
|
|
911
949
|
async goldenThreadStatus() {
|
|
912
950
|
return this.mcp.callTool("golden_thread_status", {});
|
|
@@ -923,16 +961,6 @@ var AlterClient = class {
|
|
|
923
961
|
async threadCensus(args = {}) {
|
|
924
962
|
return this.mcp.callTool("thread_census", args);
|
|
925
963
|
}
|
|
926
|
-
// ── Thirteen Seats ───────────────────────────────────────────────────
|
|
927
|
-
async seatStatus() {
|
|
928
|
-
return this.mcp.callTool("seat_status", {});
|
|
929
|
-
}
|
|
930
|
-
async respondToOffering(args) {
|
|
931
|
-
return this.mcp.callTool("respond_to_offering", args);
|
|
932
|
-
}
|
|
933
|
-
async subscribeAnnouncements(args = {}) {
|
|
934
|
-
return this.mcp.callTool("subscribe_announcements", args);
|
|
935
|
-
}
|
|
936
964
|
// ── Premium tier (x402-gated) ────────────────────────────────────────
|
|
937
965
|
async assessTraits(args, opts) {
|
|
938
966
|
return this.mcp.callTool("assess_traits", args, opts);
|
|
@@ -952,18 +980,6 @@ var AlterClient = class {
|
|
|
952
980
|
async generateMatchNarrative(args, opts) {
|
|
953
981
|
return this.mcp.callTool("generate_match_narrative", args, opts);
|
|
954
982
|
}
|
|
955
|
-
async submitBatchContext(args, opts) {
|
|
956
|
-
return this.mcp.callTool("submit_batch_context", args, opts);
|
|
957
|
-
}
|
|
958
|
-
async submitStructuredProfile(args, opts) {
|
|
959
|
-
return this.mcp.callTool("submit_structured_profile", args, opts);
|
|
960
|
-
}
|
|
961
|
-
async submitSocialLinks(args, opts) {
|
|
962
|
-
return this.mcp.callTool("submit_social_links", args, opts);
|
|
963
|
-
}
|
|
964
|
-
async attestDomain(args, opts) {
|
|
965
|
-
return this.mcp.callTool("attest_domain", args, opts);
|
|
966
|
-
}
|
|
967
983
|
async getSideQuestGraph(args, opts) {
|
|
968
984
|
return this.mcp.callTool("get_side_quest_graph", args, opts);
|
|
969
985
|
}
|
|
@@ -1057,6 +1073,8 @@ function generateCursorConfig(opts = {}) {
|
|
|
1057
1073
|
|
|
1058
1074
|
// src/types.ts
|
|
1059
1075
|
var FREE_TOOL_NAMES = [
|
|
1076
|
+
"hello_agent",
|
|
1077
|
+
"alter_resolve_handle",
|
|
1060
1078
|
"list_archetypes",
|
|
1061
1079
|
"verify_identity",
|
|
1062
1080
|
"initiate_assessment",
|
|
@@ -1064,8 +1082,6 @@ var FREE_TOOL_NAMES = [
|
|
|
1064
1082
|
"get_profile",
|
|
1065
1083
|
"query_matches",
|
|
1066
1084
|
"get_competencies",
|
|
1067
|
-
"create_identity_stub",
|
|
1068
|
-
"submit_context",
|
|
1069
1085
|
"search_identities",
|
|
1070
1086
|
"get_identity_earnings",
|
|
1071
1087
|
"get_network_stats",
|
|
@@ -1076,15 +1092,11 @@ var FREE_TOOL_NAMES = [
|
|
|
1076
1092
|
"get_agent_trust_tier",
|
|
1077
1093
|
"get_agent_portfolio",
|
|
1078
1094
|
"get_privacy_budget",
|
|
1079
|
-
"dispute_attestation",
|
|
1080
1095
|
"golden_thread_status",
|
|
1081
1096
|
"begin_golden_thread",
|
|
1082
1097
|
"complete_knot",
|
|
1083
1098
|
"check_golden_thread",
|
|
1084
|
-
"thread_census"
|
|
1085
|
-
"seat_status",
|
|
1086
|
-
"respond_to_offering",
|
|
1087
|
-
"subscribe_announcements"
|
|
1099
|
+
"thread_census"
|
|
1088
1100
|
];
|
|
1089
1101
|
var PREMIUM_TOOL_NAMES = [
|
|
1090
1102
|
"assess_traits",
|
|
@@ -1093,15 +1105,13 @@ var PREMIUM_TOOL_NAMES = [
|
|
|
1093
1105
|
"compute_belonging",
|
|
1094
1106
|
"get_match_recommendations",
|
|
1095
1107
|
"generate_match_narrative",
|
|
1096
|
-
"submit_batch_context",
|
|
1097
|
-
"submit_structured_profile",
|
|
1098
|
-
"submit_social_links",
|
|
1099
|
-
"attest_domain",
|
|
1100
1108
|
"get_side_quest_graph",
|
|
1101
1109
|
"query_graph_similarity"
|
|
1102
1110
|
];
|
|
1103
1111
|
var TOOL_TIERS = {
|
|
1104
1112
|
// L0 (free)
|
|
1113
|
+
hello_agent: 0,
|
|
1114
|
+
alter_resolve_handle: 0,
|
|
1105
1115
|
list_archetypes: 0,
|
|
1106
1116
|
verify_identity: 0,
|
|
1107
1117
|
initiate_assessment: 0,
|
|
@@ -1109,9 +1119,7 @@ var TOOL_TIERS = {
|
|
|
1109
1119
|
get_profile: 0,
|
|
1110
1120
|
query_matches: 0,
|
|
1111
1121
|
get_competencies: 0,
|
|
1112
|
-
|
|
1113
|
-
submit_context: 1,
|
|
1114
|
-
search_identities: 1,
|
|
1122
|
+
search_identities: 0,
|
|
1115
1123
|
get_identity_earnings: 0,
|
|
1116
1124
|
get_network_stats: 0,
|
|
1117
1125
|
recommend_tool: 0,
|
|
@@ -1119,8 +1127,6 @@ var TOOL_TIERS = {
|
|
|
1119
1127
|
check_assessment_status: 0,
|
|
1120
1128
|
get_earning_summary: 0,
|
|
1121
1129
|
get_privacy_budget: 0,
|
|
1122
|
-
dispute_attestation: 0,
|
|
1123
|
-
// Free tools not present in upstream TOOL_TIERS — default to 0
|
|
1124
1130
|
get_agent_trust_tier: 0,
|
|
1125
1131
|
get_agent_portfolio: 0,
|
|
1126
1132
|
golden_thread_status: 0,
|
|
@@ -1128,18 +1134,11 @@ var TOOL_TIERS = {
|
|
|
1128
1134
|
complete_knot: 0,
|
|
1129
1135
|
check_golden_thread: 0,
|
|
1130
1136
|
thread_census: 0,
|
|
1131
|
-
seat_status: 0,
|
|
1132
|
-
respond_to_offering: 0,
|
|
1133
|
-
subscribe_announcements: 0,
|
|
1134
1137
|
// L1
|
|
1135
1138
|
assess_traits: 1,
|
|
1136
1139
|
get_trait_snapshot: 1,
|
|
1137
|
-
submit_structured_profile: 1,
|
|
1138
|
-
submit_social_links: 1,
|
|
1139
|
-
attest_domain: 1,
|
|
1140
1140
|
// L2
|
|
1141
1141
|
get_full_trait_vector: 2,
|
|
1142
|
-
submit_batch_context: 2,
|
|
1143
1142
|
get_side_quest_graph: 2,
|
|
1144
1143
|
// L3
|
|
1145
1144
|
query_graph_similarity: 3,
|
|
@@ -1151,6 +1150,8 @@ var TOOL_TIERS = {
|
|
|
1151
1150
|
};
|
|
1152
1151
|
var TOOL_COSTS = {
|
|
1153
1152
|
// L0 free
|
|
1153
|
+
hello_agent: 0,
|
|
1154
|
+
alter_resolve_handle: 0,
|
|
1154
1155
|
list_archetypes: 0,
|
|
1155
1156
|
verify_identity: 0,
|
|
1156
1157
|
initiate_assessment: 0,
|
|
@@ -1158,7 +1159,6 @@ var TOOL_COSTS = {
|
|
|
1158
1159
|
get_profile: 0,
|
|
1159
1160
|
query_matches: 0,
|
|
1160
1161
|
get_competencies: 0,
|
|
1161
|
-
create_identity_stub: 0,
|
|
1162
1162
|
search_identities: 0,
|
|
1163
1163
|
get_identity_earnings: 0,
|
|
1164
1164
|
get_network_stats: 0,
|
|
@@ -1169,25 +1169,16 @@ var TOOL_COSTS = {
|
|
|
1169
1169
|
get_agent_trust_tier: 0,
|
|
1170
1170
|
get_agent_portfolio: 0,
|
|
1171
1171
|
get_privacy_budget: 0,
|
|
1172
|
-
dispute_attestation: 0,
|
|
1173
1172
|
golden_thread_status: 0,
|
|
1174
1173
|
begin_golden_thread: 0,
|
|
1175
1174
|
complete_knot: 0,
|
|
1176
1175
|
check_golden_thread: 0,
|
|
1177
1176
|
thread_census: 0,
|
|
1178
|
-
seat_status: 0,
|
|
1179
|
-
respond_to_offering: 0,
|
|
1180
|
-
subscribe_announcements: 0,
|
|
1181
1177
|
// L1 ($0.005)
|
|
1182
|
-
submit_context: 5e-3,
|
|
1183
1178
|
assess_traits: 5e-3,
|
|
1184
1179
|
get_trait_snapshot: 5e-3,
|
|
1185
|
-
submit_structured_profile: 5e-3,
|
|
1186
|
-
submit_social_links: 5e-3,
|
|
1187
|
-
attest_domain: 5e-3,
|
|
1188
1180
|
// L2 ($0.01)
|
|
1189
1181
|
get_full_trait_vector: 0.01,
|
|
1190
|
-
submit_batch_context: 0.01,
|
|
1191
1182
|
get_side_quest_graph: 0.01,
|
|
1192
1183
|
// L3 ($0.025)
|
|
1193
1184
|
query_graph_similarity: 0.025,
|
|
@@ -1199,6 +1190,8 @@ var TOOL_COSTS = {
|
|
|
1199
1190
|
};
|
|
1200
1191
|
var TOOL_BLAST_RADIUS = {
|
|
1201
1192
|
// Low: read-only reference
|
|
1193
|
+
hello_agent: "low",
|
|
1194
|
+
alter_resolve_handle: "low",
|
|
1202
1195
|
list_archetypes: "low",
|
|
1203
1196
|
verify_identity: "low",
|
|
1204
1197
|
get_engagement_level: "low",
|
|
@@ -1211,13 +1204,12 @@ var TOOL_BLAST_RADIUS = {
|
|
|
1211
1204
|
begin_golden_thread: "low",
|
|
1212
1205
|
check_golden_thread: "low",
|
|
1213
1206
|
thread_census: "low",
|
|
1214
|
-
dispute_attestation: "low",
|
|
1215
1207
|
get_identity_earnings: "low",
|
|
1216
1208
|
get_identity_trust_score: "low",
|
|
1217
1209
|
initiate_assessment: "low",
|
|
1210
|
+
get_agent_trust_tier: "low",
|
|
1211
|
+
get_agent_portfolio: "low",
|
|
1218
1212
|
// Medium: writes data or searches
|
|
1219
|
-
create_identity_stub: "medium",
|
|
1220
|
-
submit_context: "medium",
|
|
1221
1213
|
search_identities: "medium",
|
|
1222
1214
|
get_profile: "medium",
|
|
1223
1215
|
query_matches: "medium",
|
|
@@ -1225,29 +1217,17 @@ var TOOL_BLAST_RADIUS = {
|
|
|
1225
1217
|
complete_knot: "medium",
|
|
1226
1218
|
assess_traits: "medium",
|
|
1227
1219
|
get_trait_snapshot: "medium",
|
|
1228
|
-
submit_structured_profile: "medium",
|
|
1229
|
-
submit_social_links: "medium",
|
|
1230
|
-
submit_batch_context: "medium",
|
|
1231
|
-
attest_domain: "medium",
|
|
1232
1220
|
// High: returns sensitive identity data or computes scores
|
|
1233
1221
|
get_full_trait_vector: "high",
|
|
1234
1222
|
compute_belonging: "high",
|
|
1235
1223
|
get_match_recommendations: "high",
|
|
1236
1224
|
generate_match_narrative: "high",
|
|
1237
1225
|
get_side_quest_graph: "high",
|
|
1238
|
-
query_graph_similarity: "high"
|
|
1239
|
-
// Tools not in upstream TOOL_BLAST_RADIUS — default to "low"
|
|
1240
|
-
get_agent_trust_tier: "low",
|
|
1241
|
-
get_agent_portfolio: "low",
|
|
1242
|
-
seat_status: "low",
|
|
1243
|
-
respond_to_offering: "low",
|
|
1244
|
-
subscribe_announcements: "low"
|
|
1226
|
+
query_graph_similarity: "high"
|
|
1245
1227
|
};
|
|
1246
1228
|
|
|
1247
1229
|
// src/index.ts
|
|
1248
1230
|
var SDK_NAME = "@truealter/sdk";
|
|
1249
|
-
var SDK_VERSION = "0.
|
|
1231
|
+
var SDK_VERSION = "0.2.4";
|
|
1250
1232
|
|
|
1251
1233
|
export { AlterAuthError, AlterClient, AlterDiscoveryError, AlterError, AlterInvalidResponse, AlterNetworkError, AlterPaymentRequired, AlterProvenanceError, AlterRateLimited, AlterTimeoutError, AlterToolError, DEFAULT_DOMAIN, DEFAULT_ENDPOINT, DEFAULT_VERIFY_AT_ALLOWLIST, FREE_TOOL_NAMES, MCPClient, MCP_PROTOCOL_VERSION, PREMIUM_TOOL_NAMES, SDK_NAME, SDK_VERSION, TOOL_BLAST_RADIUS, TOOL_COSTS, TOOL_TIERS, X402Client, base64urlDecode, base64urlEncode, clearDiscoveryCache, decodeDid, discover, encodeDid, fetchPublicKeys, generateClaudeConfig, generateCursorConfig, generateGenericMcpConfig, generateKeypair, keypairFromPrivateKey, parsePaymentHeader, resolveVerifyAt, sign, verify, verifyProvenance, verifyToolSignatures };
|
|
1252
|
-
//# sourceMappingURL=index.js.map
|
|
1253
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truealter/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "ALTER Identity SDK — query the continuous identity field from any JavaScript/TypeScript environment",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -48,21 +48,26 @@
|
|
|
48
48
|
"keywords": [
|
|
49
49
|
"alter",
|
|
50
50
|
"identity",
|
|
51
|
+
"identity-infrastructure",
|
|
51
52
|
"mcp",
|
|
53
|
+
"model-context-protocol",
|
|
52
54
|
"ai-agent",
|
|
53
55
|
"x402",
|
|
54
56
|
"psychometric",
|
|
55
57
|
"provenance",
|
|
56
58
|
"ed25519",
|
|
57
|
-
"
|
|
59
|
+
"identity-field",
|
|
60
|
+
"belonging-probability",
|
|
61
|
+
"trait-vector",
|
|
62
|
+
"agent-identity",
|
|
63
|
+
"anthropic"
|
|
58
64
|
],
|
|
59
65
|
"repository": {
|
|
60
66
|
"type": "git",
|
|
61
|
-
"url": "https://github.com/true-alter/
|
|
62
|
-
"directory": "packages/alter-identity"
|
|
67
|
+
"url": "https://github.com/true-alter/alter-identity.git"
|
|
63
68
|
},
|
|
64
69
|
"homepage": "https://truealter.com",
|
|
65
70
|
"bugs": {
|
|
66
|
-
"url": "https://github.com/true-alter/
|
|
71
|
+
"url": "https://github.com/true-alter/alter-identity/issues"
|
|
67
72
|
}
|
|
68
73
|
}
|